@@ -75,14 +75,14 @@ <h1 id="react-concise-state">react-concise-state</h1>
75
75
// 1️⃣ create a store context providing initial state and an actions
76
76
const [context, Provider] = createStoreContext({
77
77
counter: 0
78
- }, {
78
+ }, ({ state, setState }) => ( {
79
79
// 👇 actions modify state using provided `setState`
80
- incrementBy: ({ state, setState }, increment: number) => {
80
+ incrementBy: (increment: number) => {
81
81
const newValue = state.counter + increment
82
82
setState({ counter: newValue })
83
83
},
84
- reset: ({ setState } ) => setState({ counter: 0 })
85
- })
84
+ reset: () => setState({ counter: 0 })
85
+ }))
86
86
87
87
// 2️⃣ wrap component in created provider
88
88
const App = props => {
@@ -184,23 +184,25 @@ <h4 id="actions-modifying-state"><code>actions</code> - modifying state</h4>
184
184
< li > May or may not have a payload</ li >
185
185
< li > May or may not return a value</ li >
186
186
< li > May be async</ li >
187
+ < li > May call own store actions</ li >
188
+ < li > May be chained, injected, cached, curried etc.</ li >
187
189
< li > May call other stores</ li >
188
190
< li > May be written in functional & immutable approach or in imperative approach</ li >
189
191
</ ul >
190
192
< p > To create store action in < code > react-concise-state</ code > provide a second argument to < code > createStoreContext</ code > - an object where object keys are action names and values are actions themselves.</ p >
191
193
< p > Basic examples:</ p >
192
194
< pre > < code class ="language-tsx "> // Imperative
193
- const actions = {
194
- someAction: ({state, setState}, payload) => {
195
+ const actions = ({state, setState}) => ( {
196
+ someAction: ( payload) => {
195
197
const newState = ... // do something
196
198
setState(newState)
197
199
}
198
- }
200
+ })
199
201
200
202
// Functional
201
- const actions = {
202
- someAction: ({setState}, payload) => setState(prev => { ..prev, /* do something */})
203
- }
203
+ const actions = ({setState}) => ( {
204
+ someAction: (payload) => setState(prev => { ..prev, /* do something */})
205
+ })
204
206
205
207
// Create store
206
208
createStoreContext(state, actions)</ code > </ pre >
@@ -211,19 +213,19 @@ <h4 id="actions-modifying-state"><code>actions</code> - modifying state</h4>
211
213
store.someAction('this is a payload string')</ code > </ pre >
212
214
< details > < summary > Advanced (click to expand)</ summary > < p >
213
215
< p > Payload for actions is optional. There could be any amount of payload arguments. </ p >
214
- < pre > < code class ="language-tsx "> const [context, Provider] = createStoreContext({counter: 0}, {
216
+ < pre > < code class ="language-tsx "> const [context, Provider] = createStoreContext({counter: 0}, ({state, setState}) => ( {
215
217
// No payload
216
- increment: ({state, setState} ) = setState({counter: ++state.counter}),
218
+ increment: () => setState({counter: ++state.counter}),
217
219
// If you are using functional style you can also get current state inside `setState` using callback function
218
- decrement: ({setState} ) => setState(state => ({counter: --state.counter})),
220
+ decrement: () => setState(state => ({counter: --state.counter})),
219
221
220
222
// With payload
221
- setValue: ({setState}, value) => setState({counter: value}),
222
- setValueIfMoreThan: ({state, setState}, value, limit) => {
223
+ setValue: (value) => setState({counter: value}),
224
+ setValueIfMoreThan: (value, limit) => {
223
225
if(state.counter > limit)
224
226
setState({counter: value})
225
227
}
226
- })
228
+ }))
227
229
228
230
...
229
231
@@ -242,18 +244,18 @@ <h4 id="actions-modifying-state"><code>actions</code> - modifying state</h4>
242
244
store.setValueIfMoreThan(9, 1)
243
245
// > store.counter is 1</ code > </ pre >
244
246
< p > You can get return value from actions. It also enabled awaiting async actions.</ p >
245
- < pre > < code class ="language-tsx "> const [context, Provider] = createStoreContext({todos: []}, {
247
+ < pre > < code class ="language-tsx "> const [context, Provider] = createStoreContext({todos: []}, ({setState}) => ( {
246
248
// Returning a value
247
- addTodo: ({setState}, todo) => {
249
+ addTodo: (todo) => {
248
250
const result = Api.addTodo(todo)
249
251
return result
250
252
},
251
253
// Getting todos asynchronously
252
- getTodos: async ({setState} ) => {
254
+ getTodos: async () => {
253
255
const todos = await Api.getTodos()
254
256
setState({todos})
255
257
}
256
- })
258
+ }))
257
259
258
260
...
259
261
@@ -263,23 +265,43 @@ <h4 id="actions-modifying-state"><code>actions</code> - modifying state</h4>
263
265
const result = store.addTodo('buy milk')
264
266
265
267
await store.getTodos()</ code > </ pre >
268
+ < p > You can call actions from other actions.</ p >
269
+ < pre > < code class ="language-tsx "> const [context, Provider] = createStoreContext({todos: []}, ({setState}) => ({
270
+ addTodo(todo) {
271
+ const result = Api.addTodo(todo)
272
+ this.getTodos()
273
+ },
274
+ getTodos: async () => {
275
+ const todos = await Api.getTodos()
276
+ setState({todos})
277
+ }
278
+ }))
279
+
280
+ ...
281
+
282
+ // Usage
283
+ const store = React.useContext(context)
284
+
285
+ const result = store.addTodo('buy milk')
286
+
287
+ // await store.getTodos() - don't need to call it. `.addTodo` will call it</ code > </ pre >
266
288
</ p > </ details >
267
289
< h4 id ="calling-other-stores "> Calling other stores</ h4 >
268
290
< p > Sometimes you would like to call other store action from an action. You can't use < code > React.useContext</ code > because of specific hook rules in React. Hook amount should never change during runtime and only way to supply that is to initialize all dependency contexts before bootstraping actions.</ p >
269
291
< p > You can call actions in other stores by providing dependency contexts as a 3rd parameter to < code > createStoreContext</ code > . Those contexts will be mapped to corresponding stores internally and will be available in < code > stores</ code > object in < code > {setState, action, stores}</ code > argument of action creator.</ p >
270
292
< p > Example:</ p >
271
- < pre > < code class ="language-tsx "> const [todoContext, Provider] = createStoreContext({todos: []}, {
272
- addTodo: ({state, setState}, todo) => {
293
+ < pre > < code class ="language-tsx "> const [todoContext, Provider] = createStoreContext({todos: []}, ({state, setState}) => ( {
294
+ addTodo: (todo) => {
273
295
setState({todos: [...state.todos, todo]})
274
296
},
275
- })
276
- const [mainContext, Provider] = createStoreContext({message: ''}, {
277
- someAction: ({setState, stores}, name) => {
297
+ }))
298
+ const [mainContext, Provider] = createStoreContext({message: ''}, ({setState, stores}) => ( {
299
+ someAction: (name) => {
278
300
const { todos } = stores.todoContext // stores.todoContext is a "todo store" ({todos: [], addTodo: (todo) => void})
279
301
const newMessage = `Hello, ${name}, you have ${todos.length} todos!`
280
302
setState({message: newMessage})
281
303
},
282
- }, {todoContext})
304
+ }) , {todoContext})
283
305
...
284
306
// Usage
285
307
const todoStore = React.useContext(todoContext)
0 commit comments