@reactables/react 1.0.2-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +149 -0
- package/dist/Components/StoreProvider.d.ts +9 -0
- package/dist/Components/index.d.ts +1 -0
- package/dist/Hooks/index.d.ts +2 -0
- package/dist/Hooks/useAppStore.d.ts +3 -0
- package/dist/Hooks/useReactable.d.ts +4 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +42 -0
- package/package.json +21 -0
package/README.md
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# Reactables React
|
|
2
|
+
|
|
3
|
+
## Description
|
|
4
|
+
|
|
5
|
+
Reactable bindings for React Components
|
|
6
|
+
|
|
7
|
+
## Table of Contents
|
|
8
|
+
|
|
9
|
+
1. [Installation](#installation)
|
|
10
|
+
1. [Providers](#providers)
|
|
11
|
+
1. [`StoreProvider`](#store-provider)
|
|
12
|
+
1. [Hooks](#hooks)
|
|
13
|
+
1. [`useReactable`](#use-reactable)
|
|
14
|
+
1. [`useAppStore`](#store-provider)
|
|
15
|
+
|
|
16
|
+
## Installation <a name="installation"></a>
|
|
17
|
+
|
|
18
|
+
`npm i @reactables/react`
|
|
19
|
+
|
|
20
|
+
## Providers<a name="providers"></a>
|
|
21
|
+
|
|
22
|
+
### `StoreProvider`<a name="store-provider"></a>
|
|
23
|
+
|
|
24
|
+
Used to set up a context containing one reactable responsible for managing application (global) state. The reactable can be accessed via the `useAppStore` hook in components.
|
|
25
|
+
|
|
26
|
+
**Note: The reactable used for application state must be decorated with the `storeValue` decorator to ensure subsequent subscriptions to the reactable by components receive the latest stored value.**
|
|
27
|
+
|
|
28
|
+
Example:
|
|
29
|
+
```typescript
|
|
30
|
+
// index.js
|
|
31
|
+
|
|
32
|
+
import { storeValue, RxBuilder } from '@reactables/core';
|
|
33
|
+
import React from 'react';
|
|
34
|
+
import { createRoot } from 'react-dom/client';
|
|
35
|
+
|
|
36
|
+
export interface AppState {
|
|
37
|
+
userLoggedIn: boolean
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface AppActions {
|
|
41
|
+
logout: () => void;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const config = {
|
|
45
|
+
name: 'rxAppStore',
|
|
46
|
+
initialState: {
|
|
47
|
+
userLoggedIn: false,
|
|
48
|
+
},
|
|
49
|
+
reducers: {
|
|
50
|
+
loginSuccess: () => ({ userLoggedIn: true })
|
|
51
|
+
logout: () => ({ userLoggedIn: false })
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const rxAppStore = storeValue(RxBuilder(config));
|
|
56
|
+
|
|
57
|
+
const container = document.getElementById('root');
|
|
58
|
+
const root = createRoot(container);
|
|
59
|
+
|
|
60
|
+
root.render(
|
|
61
|
+
<StoreProvider rxStore={rxAppStore}>
|
|
62
|
+
<App />
|
|
63
|
+
</StoreProvider>
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Hooks<a name="hooks"></a>
|
|
69
|
+
|
|
70
|
+
### `useReactable` <a name="use-reactable"></a>
|
|
71
|
+
|
|
72
|
+
React hook for binding a reactable to a React component. Accepts a reactable factory, dependencies (if any) and returns a tuple with the state `T`, actions `S`, and the original observable state `Observable<T>`.
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
export declare const useReactable: <T, S, U extends unknown[]>(
|
|
76
|
+
reactableFactory: (...deps: U) => Reactable<T, S>, ...deps: U
|
|
77
|
+
) => [T, S, Observable<T>];
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Example:
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
import React from 'react';
|
|
85
|
+
import { RxBuilder } from '@reactables/core';
|
|
86
|
+
import { useReactable } from '@reactables/react';
|
|
87
|
+
|
|
88
|
+
const RxToggle = (
|
|
89
|
+
initialState = false,
|
|
90
|
+
) =>
|
|
91
|
+
RxBuilder({
|
|
92
|
+
initialState,
|
|
93
|
+
name: 'rxToggle',
|
|
94
|
+
reducers: {
|
|
95
|
+
toggle: (state) => !state,
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
const Toggle = () => {
|
|
100
|
+
const [state, actions] = useReactable(RxToggle, false);
|
|
101
|
+
|
|
102
|
+
if (!state) return;
|
|
103
|
+
|
|
104
|
+
return (
|
|
105
|
+
<div>
|
|
106
|
+
<div>Toggle is: { state ? 'on' : 'off'} </div>
|
|
107
|
+
<button type="button" onClick={actions.toggle}></button>
|
|
108
|
+
</div>
|
|
109
|
+
)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export default Toggle;
|
|
113
|
+
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### `useAppStore`<a name="useAppStore"></a>
|
|
117
|
+
|
|
118
|
+
React hook for accessing reactable provided by [`StoreProvider`](#store-provider) and binding it to a React component. Like [`useReactable`](use-reactable) it returns a tuple with the state `T`, actions `S`, and the original observable state `Observable<T>`.
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
export declare const useAppStore: <T, S = ActionMap>() => [T, S, Observable<T>];
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Example using the setup from [`StoreProvider`](#store-provider) example above:
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
import React from 'react';
|
|
128
|
+
import { useAppStore } from '@reactables/react';
|
|
129
|
+
import { AppState, AppActions } from '../index'
|
|
130
|
+
|
|
131
|
+
const App = () => {
|
|
132
|
+
const [appState, appActions] = useAppStore<AppState, AppActions>();
|
|
133
|
+
|
|
134
|
+
if (!appState) return;
|
|
135
|
+
|
|
136
|
+
return (
|
|
137
|
+
<>
|
|
138
|
+
<div>
|
|
139
|
+
User is {appState.userLoggedIn ? 'logged in': 'not logged in'}.
|
|
140
|
+
</div>
|
|
141
|
+
<button type="button" onClick={appActions.logout}>Logout</button>
|
|
142
|
+
</>
|
|
143
|
+
|
|
144
|
+
)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export default App;
|
|
148
|
+
|
|
149
|
+
```
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Reactable } from '@reactables/core';
|
|
3
|
+
export declare const StoreContext: React.Context<Reactable<unknown, unknown>>;
|
|
4
|
+
interface StoreProviderProps<T, S> {
|
|
5
|
+
rxStore: Reactable<T, S>;
|
|
6
|
+
children?: React.ReactNode;
|
|
7
|
+
}
|
|
8
|
+
export declare const StoreProvider: <T, S>({ rxStore, children }: StoreProviderProps<T, S>) => React.JSX.Element;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { StoreProvider } from './StoreProvider';
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { Observable } from 'rxjs';
|
|
2
|
+
import { Reactable, Action } from '@reactables/core';
|
|
3
|
+
export type HookedReactable<T, S> = [T, S, Observable<T>, Observable<Action<unknown>>?];
|
|
4
|
+
export declare const useReactable: <T, S, U extends unknown[]>(reactableFactory: (...props: U) => Reactable<T, S>, ...props: U) => HookedReactable<T, S>;
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var React = require('react');
|
|
6
|
+
|
|
7
|
+
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
8
|
+
|
|
9
|
+
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
|
|
10
|
+
|
|
11
|
+
var StoreContext = React__default["default"].createContext(null);
|
|
12
|
+
var StoreProvider = function (_a) {
|
|
13
|
+
var rxStore = _a.rxStore, children = _a.children;
|
|
14
|
+
return React__default["default"].createElement(StoreContext.Provider, { value: rxStore }, rxStore && children);
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
var useReactable = function (reactableFactory) {
|
|
18
|
+
var props = [];
|
|
19
|
+
for (var _i = 1; _i < arguments.length; _i++) {
|
|
20
|
+
props[_i - 1] = arguments[_i];
|
|
21
|
+
}
|
|
22
|
+
var _a = React.useMemo(function () { return reactableFactory.apply(void 0, props); }, []), state$ = _a[0], actions = _a[1], messages$ = _a[2];
|
|
23
|
+
var _b = React.useState(), state = _b[0], setState = _b[1];
|
|
24
|
+
React.useEffect(function () {
|
|
25
|
+
var subscription = state$.subscribe(function (result) {
|
|
26
|
+
setState(result);
|
|
27
|
+
});
|
|
28
|
+
var unsubscribe = subscription.unsubscribe.bind(subscription);
|
|
29
|
+
return unsubscribe;
|
|
30
|
+
}, [state$]);
|
|
31
|
+
return [state, actions, state$, messages$];
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
var useAppStore = function () {
|
|
35
|
+
var rxStore$ = React.useContext(StoreContext);
|
|
36
|
+
var rxStore = useReactable(function () { return rxStore$; });
|
|
37
|
+
return rxStore;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
exports.StoreProvider = StoreProvider;
|
|
41
|
+
exports.useAppStore = useAppStore;
|
|
42
|
+
exports.useReactable = useReactable;
|
package/package.json
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@reactables/react",
|
|
3
|
+
"description": "React Helpers for reactables",
|
|
4
|
+
"main": "dist/index.js",
|
|
5
|
+
"files": [
|
|
6
|
+
"dist"
|
|
7
|
+
],
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "rimraf dist && rollup --config",
|
|
10
|
+
"lint": "eslint --max-warnings 0 \"src/**/*.ts*\" && prettier --check src/",
|
|
11
|
+
"fix": "eslint --fix \"src/**/*.ts*\" && prettier --write \"src/**/*.(ts*|scss)\""
|
|
12
|
+
},
|
|
13
|
+
"author": "David Lai",
|
|
14
|
+
"license": "ISC",
|
|
15
|
+
"dependencies": {},
|
|
16
|
+
"peerDependencies": {
|
|
17
|
+
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
|
18
|
+
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
|
19
|
+
},
|
|
20
|
+
"version": "1.0.2-beta.0"
|
|
21
|
+
}
|