@cleanweb/react 1.1.1-beta.9 → 2.0.1-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 +242 -187
- package/README.old.md +342 -0
- package/build/base/merged-state.d.ts +1 -0
- package/build/base/merged-state.js +3 -2
- package/build/base/methods.d.ts +39 -6
- package/build/base/methods.js +45 -80
- package/build/base/state/class-types.d.ts +17 -0
- package/build/base/state/class-types.js +2 -0
- package/build/base/state/class.d.ts +14 -0
- package/build/base/{state.js → state/class.js} +4 -51
- package/build/base/state/hook-types.d.ts +11 -0
- package/build/base/state/hook-types.js +2 -0
- package/build/base/state/hooks.d.ts +11 -0
- package/build/base/state/hooks.js +57 -0
- package/build/base/state/index.d.ts +4 -0
- package/build/base/state/index.js +9 -0
- package/build/classy/class/index.d.ts +102 -0
- package/build/classy/class/index.js +147 -0
- package/build/classy/class/types/class/instance.d.ts +12 -0
- package/build/classy/class/types/class/instance.js +2 -0
- package/build/classy/class/types/class/static.d.ts +9 -0
- package/build/classy/class/types/class/static.js +12 -0
- package/build/classy/class/types/extractor.d.ts +6 -0
- package/build/classy/class/types/extractor.js +2 -0
- package/build/classy/class/utils/function-name.d.ts +2 -0
- package/build/classy/class/utils/function-name.js +17 -0
- package/build/classy/class/utils/rerender.d.ts +1 -0
- package/build/classy/class/utils/rerender.js +11 -0
- package/build/classy/class/utils/use-component/index.d.ts +6 -0
- package/build/classy/class/utils/use-component/index.js +17 -0
- package/build/classy/class/utils/use-component/types.d.ts +22 -0
- package/build/classy/class/utils/use-component/types.js +2 -0
- package/build/classy/instance/index.d.ts +94 -0
- package/build/classy/{instance.js → instance/index.js} +58 -38
- package/build/classy/instance/mount-callbacks.d.ts +4 -0
- package/build/classy/instance/mount-callbacks.js +30 -0
- package/build/classy/instance/types/hook.d.ts +16 -0
- package/build/classy/instance/types/hook.js +2 -0
- package/build/classy/instance/types/instance.d.ts +11 -0
- package/build/classy/instance/types/instance.js +2 -0
- package/build/classy/instance/types/static.d.ts +11 -0
- package/build/classy/instance/types/static.js +17 -0
- package/build/classy/logic/index.d.ts +42 -0
- package/build/classy/logic/index.js +122 -0
- package/build/classy/logic/types/hook.d.ts +24 -0
- package/build/classy/logic/types/hook.js +2 -0
- package/build/classy/logic/types/instance.d.ts +18 -0
- package/build/classy/logic/types/instance.js +2 -0
- package/build/classy/logic/types/static.d.ts +17 -0
- package/build/classy/logic/types/static.js +2 -0
- package/build/globals.d.ts +23 -33
- package/build/globals.js +2 -20
- package/build/index.d.ts +1 -1
- package/build/index.js +2 -1
- package/build/tsconfig.json +3 -0
- package/package.json +8 -6
- package/build/base/state.d.ts +0 -31
- package/build/classy/class.d.ts +0 -24
- package/build/classy/class.js +0 -132
- package/build/classy/instance.d.ts +0 -61
- package/build/classy/logic.d.ts +0 -20
- package/build/classy/logic.js +0 -82
- package/build/globals.private.d.ts +0 -44
- package/build/globals.private.js +0 -34
package/README.md
CHANGED
@@ -1,76 +1,153 @@
|
|
1
|
-
#
|
1
|
+
# Object Oriented Programming for React
|
2
|
+
This package provides a number of tools for creating React function components with object-oriented code. With Oore, you can avoid common errors, and write complex components that are cleaner, better structured, and eassier to read & understand.
|
2
3
|
|
3
|
-
|
4
|
-
This package provides a suite of tools for writing cleaner React function components. It is particularly useful for larger components with lots of state variables and multiple closure functions that need to access those variables. The most likely use cases will use one of the two main exported members.
|
4
|
+
Oore is written in Typescript and all exports are fully typed.
|
5
5
|
|
6
|
-
|
7
|
-
|
6
|
+
## Usage
|
7
|
+
### Clean State
|
8
|
+
The `useCleanState` hook provides a clean API for working with multiple state variables in a unified way. The example below demonstrates how to use it.
|
8
9
|
|
9
|
-
**Before**
|
10
10
|
```jsx
|
11
|
+
const initialState = {
|
12
|
+
label: 'Click me',
|
13
|
+
clicked: false,
|
14
|
+
inputValue: {},
|
15
|
+
};
|
16
|
+
// or
|
17
|
+
const getInitialState = (props) => {
|
18
|
+
return {
|
19
|
+
label: props.label,
|
20
|
+
clicked: false,
|
21
|
+
inputValue: {},
|
22
|
+
};
|
23
|
+
};
|
24
|
+
|
11
25
|
const Button = (props) => {
|
12
|
-
const
|
26
|
+
const state = useCleanState(initialState);
|
27
|
+
// or
|
28
|
+
const state = useCleanState(getInitialState, props);
|
29
|
+
|
30
|
+
|
31
|
+
const onClick = useCallback(() => {
|
32
|
+
state.clicked = true;
|
33
|
+
// or
|
34
|
+
state.putMany({
|
35
|
+
label: 'Loading',
|
36
|
+
clicked: true,
|
37
|
+
});
|
38
|
+
// or
|
39
|
+
state.put.clicked(true);
|
40
|
+
// or
|
41
|
+
state.put.clicked((oldClicked) => !oldClicked);
|
42
|
+
}, []);
|
43
|
+
|
44
|
+
return <>
|
45
|
+
<CustomInput setValue={state.put.inputValue}>
|
46
|
+
|
47
|
+
<button onClick={onClick}>
|
48
|
+
{state.label}
|
49
|
+
</button>
|
50
|
+
</>;
|
51
|
+
}
|
52
|
+
```
|
13
53
|
|
14
|
-
|
15
|
-
const [state2, setState2] = useState();
|
16
|
-
const [label, setLabel] = useState('Click me');
|
17
|
-
const [submitted, setSubmitted] = useState(false);
|
54
|
+
> **Note:** You can call `useCleanState` multiple times in the same component, allowing you to group related state values into separate objects.
|
18
55
|
|
19
|
-
|
56
|
+
> **Note:** Each top-level key in your initial state object gets a separate call to `React.useState`, and `state.put[key]()` is a proxy for the setter function returned from `useState`. So using this hook is fundamentally the same as calling `useState` directly for each value. What `useCleanState` provides is a way to unify those values and a convenient API for updating them.
|
20
57
|
|
21
|
-
|
22
|
-
externalDataSource.subscribe((data) => {
|
23
|
-
setLabel(data.label);
|
24
|
-
});
|
25
|
-
}, [setLabel]);
|
58
|
+
[Read the `useCleanState` docs]() for more details.
|
26
59
|
|
27
|
-
|
60
|
+
### Methods
|
61
|
+
The `useMethods` hook lets you manage the closures that your component uses in a separate class, keeping the body of the component clean and easier to read. With `useMethods`, your functions are not recreated on every render. Yet, every method of your component is guaranteed to always have access to the latest props and state without the need for a dependencty array.
|
28
62
|
|
29
|
-
|
63
|
+
```jsx
|
64
|
+
class ButtonMethods {
|
65
|
+
submit = () => {
|
66
|
+
const { state1, state2 } = this.state;
|
30
67
|
sendData(state1, state2);
|
31
|
-
|
32
|
-
}
|
68
|
+
this.state.submitted = true;
|
69
|
+
}
|
33
70
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
71
|
+
doSomething = () => {
|
72
|
+
console.table(this.props);
|
73
|
+
}
|
74
|
+
}
|
75
|
+
|
76
|
+
const initialState = {
|
77
|
+
value1: undefined,
|
78
|
+
value2: null,
|
79
|
+
label: 'Click me',
|
80
|
+
submitted: false,
|
81
|
+
}
|
82
|
+
|
83
|
+
const Button = (props) => {
|
84
|
+
const state = useCleanState(initialState);
|
85
|
+
const methods = useMethods(ButtonMethods, state, props);
|
86
|
+
|
87
|
+
useEffect(methods.doSomething, []);
|
88
|
+
|
89
|
+
return (
|
90
|
+
<button onClick={methods.submit}>
|
91
|
+
{state.label}
|
38
92
|
</button>
|
39
|
-
|
93
|
+
);
|
40
94
|
}
|
41
95
|
```
|
42
96
|
|
43
|
-
|
97
|
+
`useMethods` only accepts a single state object. So if you are using multiple calls to `useCleanState`, you may have to group them into a single object when calling `useMethods`.
|
98
|
+
|
99
|
+
```jsx
|
100
|
+
const getDefaultValues = (props) => ({/* ... */});
|
101
|
+
|
102
|
+
const Button = (props) => {
|
103
|
+
const formValues = useCleanState(getDefaultValues, props);
|
104
|
+
const apiData = useCleanState({});
|
105
|
+
|
106
|
+
const multiState = { formValues, apiData };
|
107
|
+
const methods = useMethods(ButtonMethods, multiState, props);
|
108
|
+
|
109
|
+
// ...
|
110
|
+
}
|
111
|
+
```
|
112
|
+
|
113
|
+
[Read the `useMethods` docs]() for more details.
|
114
|
+
|
115
|
+
### Logic
|
116
|
+
The `useLogic` hook is an expansion of `useMethods`, with the aim of being a more holistic solution. It combines the functionality of `useCleanState` and `useMethods`. In addition, it allows you to externalize _all_ of your component's logic, not just closures and state. Essentially, this means being able to call hooks from within the class, rather than having to do so within the component body.
|
117
|
+
|
44
118
|
```jsx
|
45
119
|
class ButtonLogic {
|
46
120
|
static getInitialState = () => {
|
47
121
|
return {
|
48
|
-
|
49
|
-
|
122
|
+
value1: undefined,
|
123
|
+
value2: null,
|
50
124
|
label: 'Click me',
|
51
125
|
submitted: false,
|
52
126
|
};
|
53
127
|
}
|
54
128
|
|
55
|
-
submit = () => {
|
56
|
-
const {
|
57
|
-
sendData(
|
129
|
+
submit = async () => {
|
130
|
+
const { value1, value2 } = this.state;
|
131
|
+
await sendData(value1, value2);
|
58
132
|
this.state.submitted = true;
|
59
133
|
}
|
60
134
|
|
61
|
-
|
62
|
-
|
63
|
-
this.state.label = data.label;
|
64
|
-
});
|
135
|
+
doSomething = () => {
|
136
|
+
// ...
|
65
137
|
}
|
66
138
|
|
67
139
|
useHooks = () => {
|
68
140
|
const { param } = this.props;
|
69
141
|
|
70
|
-
useEffect(this.
|
142
|
+
useEffect(this.doSomething, []);
|
143
|
+
|
71
144
|
const memoizedValue = useMemo(() => getValue(param), [param]);
|
145
|
+
const value2 = useCustomHook();
|
72
146
|
|
73
|
-
return {
|
147
|
+
return {
|
148
|
+
memoizedValue,
|
149
|
+
value2,
|
150
|
+
};
|
74
151
|
}
|
75
152
|
}
|
76
153
|
|
@@ -87,203 +164,164 @@ const Button = (props) => {
|
|
87
164
|
}
|
88
165
|
```
|
89
166
|
|
90
|
-
|
167
|
+
[Read the `useLogic` docs]() for more details.
|
91
168
|
|
92
|
-
|
93
|
-
|
94
|
-
For a fuller discussion of how `useLogic` works, start at the [clean-state documentation](https://cleanjsweb.github.io/neat-react/clean-state/index).
|
95
|
-
For an API reference, see the [API reference](https://cleanjsweb.github.io/neat-react/logic/api).
|
169
|
+
### Lifecycle (`useInstance`)
|
170
|
+
The `useInstance` hook provides a simple approach for working with your components lifecycle. It includes all the features of [`useLogic`](#logic), and adds special lifecycle methods. This gives you a declarative way to run certain code at specific stages of your component's life time. You will likely find this to be less error prone and much easier to reason about than the imperative approach of using React's hooks directly.
|
96
171
|
|
172
|
+
```jsx
|
173
|
+
/** Button Component Class. */
|
174
|
+
class ButtonCC extends ComponentInstance {
|
175
|
+
// ...
|
176
|
+
// Static method(s), same as useLogic...
|
177
|
+
// ...
|
97
178
|
|
98
|
-
### Working With Lifecycle, and Migrating From a React.Component Class to a Function Component
|
99
|
-
In addition to having cleaner and more structured component logic, you can also simplify the process of working with your component's lifecycle with the final two exported members. The `useInstance` hook builds on the functionality of `useLogic` and adds lifecyle methods to the class. This means the class can now be thought of as truly representing a single instance of a React component. The `ClassComponent` class extends this to its fullest by allowing you to write the function component itself as a method within the class, and removing the need to explicitly call `useInstance`.
|
100
179
|
|
101
|
-
|
102
|
-
```jsx
|
103
|
-
const Button = (props) => {
|
104
|
-
const [state1, setState1] = useState(props.defaultValue);
|
105
|
-
const [state2, setState2] = useState();
|
106
|
-
const [label, setLabel] = useState('Click me');
|
107
|
-
const [submitted, setSubmitted] = useState(false);
|
108
|
-
const [store, updateStore] = useGlobalStore();
|
109
|
-
|
110
|
-
// Required to run once *before* the component mounts.
|
111
|
-
const memoizedValue = useMemo(() => getValue(), []);
|
112
|
-
|
113
|
-
// Required to run once *after* the component mounts.
|
114
|
-
useEffect(() => {
|
115
|
-
const unsubscribe = externalDataSource.subscribe((data) => {
|
116
|
-
setLabel(data.label);
|
117
|
-
});
|
180
|
+
/* Lifecycle Methods */
|
118
181
|
|
119
|
-
|
182
|
+
beforeMount = () => {
|
183
|
+
// Runs before the component is first rendered.
|
184
|
+
// This is implemented using useMemo.
|
185
|
+
}
|
120
186
|
|
121
|
-
|
187
|
+
onMount = () => {
|
188
|
+
// Runs after the component is first rendered.
|
189
|
+
// Same as `useEffect(() => {}, []);`
|
122
190
|
|
123
191
|
return () => {
|
124
|
-
|
125
|
-
|
192
|
+
// Required clean up function must be returned.
|
193
|
+
// Return an empty function if you have no cleanup.
|
126
194
|
};
|
127
|
-
}
|
128
|
-
|
129
|
-
// Run *after* every render.
|
130
|
-
useEffect(() => {
|
131
|
-
doSomething();
|
132
|
-
return () => {};
|
133
|
-
})
|
134
|
-
|
135
|
-
const submit = useCallback(() => {
|
136
|
-
sendData(state1, state2);
|
137
|
-
setSubmitted(true);
|
138
|
-
}, [state1]);
|
139
|
-
|
140
|
-
// Run before every render.
|
141
|
-
const text = `${label}, please.`;
|
195
|
+
}
|
142
196
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
)) : null}
|
147
|
-
<button onClick={submit}>
|
148
|
-
{text}
|
149
|
-
</button>
|
150
|
-
</>;
|
151
|
-
}
|
197
|
+
beforeRender = () => {
|
198
|
+
// Runs before every single render.
|
199
|
+
// Same as code placed before the return statement in a function component.
|
152
200
|
|
153
|
-
|
154
|
-
|
201
|
+
// Example: Generate display values from state and props,
|
202
|
+
// and return them for use in your JSX template.
|
203
|
+
const displayValue2 = this.hooks.memoizedValue + this.state.value2;
|
155
204
|
|
156
|
-
|
157
|
-
|
158
|
-
class Button extends ClassComponent {
|
159
|
-
static getInitialState = (props) => {
|
205
|
+
// The optional returned object will be available
|
206
|
+
// on the created instance as `instance.templateContext`
|
160
207
|
return {
|
161
|
-
|
162
|
-
|
163
|
-
label: 'Click me',
|
164
|
-
submitted: false,
|
208
|
+
intro: `Hello, ${this.props.name}`,
|
209
|
+
displayValue2,
|
165
210
|
};
|
166
|
-
}
|
167
211
|
|
168
|
-
|
169
|
-
|
170
|
-
return { store, updateStore };
|
171
|
-
}
|
172
|
-
|
173
|
-
/***************************
|
174
|
-
* New Lifecycle Methods *
|
175
|
-
***************************/
|
176
|
-
|
177
|
-
beforeMount = () => {
|
178
|
-
this.memoizedValue = getValue();
|
212
|
+
// PS: For any expensive logic, you should wrap it
|
213
|
+
// in useMemo and move it into the useHooks method instead.
|
179
214
|
}
|
180
215
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
window.addEventListener('resize', this.onWindowResize);
|
216
|
+
onRender = () => {
|
217
|
+
// Runs after every single render.
|
218
|
+
// Same as `useEffect(() => {});`
|
185
219
|
|
186
|
-
// Return cleanup callback.
|
187
220
|
return () => {
|
188
|
-
|
189
|
-
|
221
|
+
// Required clean up function must be returned.
|
222
|
+
// Return an empty function if you have no cleanup.
|
190
223
|
};
|
191
224
|
}
|
192
225
|
|
193
|
-
|
194
|
-
|
226
|
+
cleanUp = () => {
|
227
|
+
// Runs when the component is unmounted.
|
228
|
+
// Similar to the function returned by `onMount`.
|
195
229
|
}
|
196
230
|
|
197
|
-
|
198
|
-
onRender = () => {
|
199
|
-
doSomething();
|
231
|
+
/* [End] Lifecycle Methods */
|
200
232
|
|
201
|
-
// Return cleanup callback.
|
202
|
-
return () => {};
|
203
|
-
}
|
204
233
|
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
/***************************
|
211
|
-
* [End] Lifecycle Methods *
|
212
|
-
***************************/
|
234
|
+
// ...
|
235
|
+
// Other instance methods, same as useLogic...
|
236
|
+
// ...
|
237
|
+
}
|
213
238
|
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
239
|
+
// Button Template
|
240
|
+
const Button = (props) => {
|
241
|
+
const self = useInstance(ButtonCC, props);
|
242
|
+
const ctx = self.templateContext;
|
218
243
|
|
219
|
-
|
244
|
+
return <>
|
245
|
+
<p>{ctx.intro}</p>
|
246
|
+
<button onClick={self.submit}>
|
247
|
+
{self.state.label}
|
248
|
+
</button>
|
249
|
+
</>;
|
250
|
+
}
|
251
|
+
```
|
220
252
|
|
221
|
-
|
222
|
-
// The effect is the same as if you called the setter function, which is available through `state.put.submitted(true)`.
|
223
|
-
this.state.submitted = true;
|
224
|
-
}
|
253
|
+
[Read the `useInstance` docs]() for more details.
|
225
254
|
|
226
|
-
|
227
|
-
|
228
|
-
}
|
255
|
+
### Class Component
|
256
|
+
With `useInstance`, pretty much every aspect of your component is now part of the class, except for the JSX template. The `ClassComponent` class takes that final step and provides a fully integrated class-based React component.
|
229
257
|
|
230
|
-
|
231
|
-
const unsubscribe = externalDataSource.subscribe((data) => {
|
232
|
-
this.state.label = data.label;
|
233
|
-
});
|
258
|
+
If you're currently maintaining older components written with the old `React.Component` class and you would like to rewrite them as function components with hooks, porting them to `ClassComponent` will _significantly_ simplify and speed up the migration process. You can access all the latest React features, without changing the overall structure of your existing component classes.
|
234
259
|
|
235
|
-
return unsubscribe;
|
236
|
-
}
|
237
260
|
|
238
|
-
|
239
|
-
|
240
|
-
|
261
|
+
```jsx
|
262
|
+
class Button extends ClassComponent {
|
263
|
+
/** See the description of the `RC` property below this example. */
|
264
|
+
static RC = Button.extract();
|
265
|
+
// Or...
|
266
|
+
static RC = Button.FC();
|
267
|
+
// Or, using `this`, which refers to the class itself
|
268
|
+
// when the static keyword is present...
|
269
|
+
static RC = this.extract();
|
270
|
+
// Or...
|
271
|
+
static RC = this.FC();
|
241
272
|
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
</p>
|
246
|
-
));
|
247
|
-
}
|
273
|
+
// ...
|
274
|
+
// Other static and instance members, same as useInstance...
|
275
|
+
// ...
|
248
276
|
|
249
|
-
/** Button Template */
|
250
|
-
Render = () => {
|
251
|
-
const { Paragraphs, submit, state } = this;
|
252
277
|
|
253
|
-
|
254
|
-
|
278
|
+
beforeRender = () => {
|
279
|
+
const displayValue2 = this.hooks.memoizedValue + this.state.value2;
|
255
280
|
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
281
|
+
return {
|
282
|
+
intro: `Hello, ${this.props.name}`,
|
283
|
+
displayValue2,
|
284
|
+
};
|
285
|
+
}
|
261
286
|
|
262
|
-
|
263
|
-
|
287
|
+
/**
|
288
|
+
* Button Template.
|
289
|
+
* @param ctx - The `templateContext` object returned in `beforeRender`.
|
290
|
+
* Will be `undefined` if nothing is returned by `beforeRender`.
|
291
|
+
*/
|
292
|
+
template = (ctx) => (
|
293
|
+
<section>
|
294
|
+
<p>{ctx.intro}</p>
|
295
|
+
|
296
|
+
<button onClick={this.submit}>
|
297
|
+
{this.state.label}
|
264
298
|
</button>
|
265
|
-
|
266
|
-
|
299
|
+
</section>
|
300
|
+
);
|
267
301
|
}
|
268
302
|
|
269
|
-
|
270
|
-
|
303
|
+
export default Button.RC;
|
304
|
+
// Or render directly with `<Button.RC />`.
|
271
305
|
```
|
272
306
|
|
273
|
-
|
307
|
+
Every class derived from the base `ClassComponent` is not itself a React component. Instead, it has a static `extract()` method (also aliased as `FC()` for "Function Component") which returns a function component that can be rendered like any other React component. Each instance of this function component mounted in the React tree creates it's own separate instance of your `ClassComponent` class. To make it easier to use the class component directly, you should create a static property that holds the function component returned by `extract`. The recommended convention is to use the name `RC` (for "React Component"). Such a class can then easily be rendered as JSX by writing `<MyComponent.RC />`.
|
308
|
+
|
309
|
+
[Read the `ClassComponent` docs]() for more details.
|
274
310
|
|
275
|
-
At its core, any component you write with `ClassComponent` is still just a React function component, with some supporting logic around it. This has the added advantage of making it significantly easier to migrate class components written with `React.Component` to the newer hooks-based function components, while still maintaining the overall structure of a class component, and the advantages that the class component approach provided.
|
276
311
|
|
277
|
-
|
278
|
-
For more details on the lifecycle methods and other API reference, see the [`ClassComponent` API docs](https://cleanjsweb.github.io/neat-react/class-component/api).
|
312
|
+
### Other Exports
|
279
313
|
|
280
|
-
|
281
|
-
If you
|
314
|
+
#### The `<Use>` Component
|
315
|
+
If you simply want to use hooks in your `React.Component` class without having to rewrite anything, this package also exports a `<Use>` component that helps you achieve this easily. Here's how to use it.
|
282
316
|
|
283
317
|
```jsx
|
318
|
+
import { useGlobalStore } from '@/hooks/store';
|
319
|
+
|
284
320
|
class Button extends React.Component {
|
285
|
-
|
286
|
-
this.
|
321
|
+
syncGlobalStore = ([store, updateStore]) => {
|
322
|
+
if (this.state.userId !== store.userId) {
|
323
|
+
this.setState({ userId: store.userId });
|
324
|
+
}
|
287
325
|
this.store = store;
|
288
326
|
this.updateStore = updateStore;
|
289
327
|
}
|
@@ -291,7 +329,7 @@ class Button extends React.Component {
|
|
291
329
|
UseHooks = () => {
|
292
330
|
return <>
|
293
331
|
<Use hook={useGlobalStore}
|
294
|
-
onUpdate={
|
332
|
+
onUpdate={syncGlobalStore}
|
295
333
|
argumentsList={[]}
|
296
334
|
key="useGlobalStore"
|
297
335
|
/>
|
@@ -309,3 +347,20 @@ class Button extends React.Component {
|
|
309
347
|
}
|
310
348
|
}
|
311
349
|
```
|
350
|
+
|
351
|
+
The provided hook is called with the `argumentsList` array passed in (the array is spread, so each item in the list is a separate argument). The return value from the hook is passed on to the `onUpdate` callback. So you can use this to update your component's state and trigger a rerender when something changes.
|
352
|
+
|
353
|
+
#### Merged State
|
354
|
+
This package also exports a `useMergedState` hook, which provides all the same features as `useCleanState`, but with a slightly different implementation.
|
355
|
+
|
356
|
+
The `useCleanState` hook is designed to exactly mirror how function components are usually written: a separate `React.useState` call for each distinct value. `useMergedState` takes a simpler approach by making just one `React.useState` call for the entire `initialState` object. Functionally though, the effect is probably the same.
|
357
|
+
|
358
|
+
It is recommended that you use `useCleanState` instead of this since that implementation is truer to how `React.useState` is commonly used. `useMergedState` may be removed in future versions.
|
359
|
+
|
360
|
+
### Issues
|
361
|
+
If you observe an issue or bug, please report it by creating an issue on the [Oore repo on GitHub]().
|
362
|
+
|
363
|
+
#### Known Issues
|
364
|
+
Methods on your component classes may not be updated as expected during HMR. So fully refreshing the page may sometimes be required while developing with Oore. A fix for this is being investigated.
|
365
|
+
|
366
|
+
|