Skip to content

Commit 057f3da

Browse files
committed
perf(useStore): create/clean hash only when component mount/unmount
re #46
1 parent b5e82af commit 057f3da

File tree

2 files changed

+100
-21
lines changed

2 files changed

+100
-21
lines changed

README.md

Lines changed: 90 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ const Todo = {
2323
items: ['Install react-model', 'Read github docs', 'Build App']
2424
},
2525
actions: {
26-
add: (s, actions, todo) => {
26+
add: todo => {
2727
// s is the readonly version of state
2828
// you can also return partial state here but don't need to keep immutable manually
2929
// state is the mutable state
@@ -33,14 +33,14 @@ const Todo = {
3333
}
3434

3535
// Model Register
36-
const { useStore } = Model({ Todo })
36+
const { useStore } = Model(Todo)
3737

3838
const App = () => {
3939
return <TodoList />
4040
}
4141

4242
const TodoList = () => {
43-
const [state, actions] = useStore('Todo')
43+
const [state, actions] = useStore()
4444
return <div>
4545
<Addon handler={actions.add} />
4646
{state.items.map((item, index) => (<Todo key={index} item={item} />))}
@@ -89,6 +89,10 @@ npm install react-model
8989

9090
Every model have their own state and actions.
9191

92+
<details>
93+
<summary><del>old model</del> (will be deprecated in v3.0)</summary>
94+
<p>
95+
9296
```typescript
9397
const initialState = {
9498
counter: 0,
@@ -111,7 +115,7 @@ interface ActionsParamType = {
111115
get: undefined
112116
} // You only need to tag the type of params here !
113117

114-
const Model: ModelType<StateType, ActionsParamType> = {
118+
const model: ModelType<StateType, ActionsParamType> = {
115119
actions: {
116120
increment: async (state, _, params) => {
117121
return {
@@ -144,7 +148,73 @@ const Model: ModelType<StateType, ActionsParamType> = {
144148
state: initialState
145149
}
146150

147-
export default Model
151+
export default model
152+
153+
// You can use these types when use Class Components.
154+
// type ConsumerActionsType = getConsumerActionsType<typeof Model.actions>
155+
// type ConsumerType = { actions: ConsumerActionsType; state: StateType }
156+
// type ActionType = ConsumerActionsType
157+
// export { ConsumerType, StateType, ActionType }
158+
```
159+
</p>
160+
</details>
161+
162+
```typescript
163+
const initialState = {
164+
counter: 0,
165+
light: false,
166+
response: {}
167+
}
168+
169+
interface StateType = {
170+
counter: number
171+
light: boolean
172+
response: {
173+
code?: number
174+
message?: string
175+
}
176+
}
177+
178+
interface ActionsParamType = {
179+
increment: number
180+
openLight: undefined
181+
get: undefined
182+
} // You only need to tag the type of params here !
183+
184+
const model: NextModelType<StateType, ActionsParamType> = {
185+
actions: {
186+
increment: async (payload, { state }) => {
187+
return {
188+
counter: state.counter + (params || 1)
189+
}
190+
},
191+
openLight: async (_, { state, actions }) => {
192+
await actions.increment(1) // You can use other actions within the model
193+
await actions.get() // support async functions (block actions)
194+
actions.get()
195+
await actions.increment(1) // + 1
196+
await actions.increment(1) // + 2
197+
await actions.increment(1) // + 3 as expected !
198+
return { light: !state.light }
199+
},
200+
get: async () => {
201+
await new Promise((resolve, reject) =>
202+
setTimeout(() => {
203+
resolve()
204+
}, 3000)
205+
)
206+
return {
207+
response: {
208+
code: 200,
209+
message: `${new Date().toLocaleString()} open light success`
210+
}
211+
}
212+
}
213+
},
214+
state: initialState
215+
}
216+
217+
export default Model(model)
148218

149219
// You can use these types when use Class Components.
150220
// type ConsumerActionsType = getConsumerActionsType<typeof Model.actions>
@@ -157,7 +227,7 @@ export default Model
157227

158228
### Model Register
159229

160-
react-model keep the state and actions in a separate store. So you need to register them before using.
230+
react-model keep the state and actions in the separate private store. So you need to register them if you want to use them as the public models.
161231

162232
`model/index.ts`
163233

@@ -166,9 +236,9 @@ import { Model } from 'react-model'
166236
import Home from '../model/home'
167237
import Shared from '../model/shared'
168238

169-
const stores = { Home, Shared }
239+
const models = { Home, Shared }
170240

171-
export const { getInitialState, useStore, getState, getActions, subscribe, unsubscribe } = Model(stores)
241+
export const { getInitialState, useStore, getState, actions, subscribe, unsubscribe } = Model(models)
172242
```
173243

174244
[⇧ back to top](#table-of-contents)
@@ -180,7 +250,7 @@ The actions return from useStore can invoke the dom changes.
180250

181251
The execution of actions returned by useStore will invoke the rerender of current component first.
182252

183-
It's the only difference between the actions returned by useStore and getActions now.
253+
It's the only difference between the actions returned by useStore and actions now.
184254

185255
```tsx
186256
import React from 'react'
@@ -251,9 +321,9 @@ const BasicHook = () => {
251321

252322
### actions
253323

254-
You can call other models' actions with getActions api
324+
You can call other models' actions with actions api
255325

256-
getActions can be used in both class components and functional components.
326+
actions can be used in both class components and functional components.
257327

258328
```js
259329
import { actions } from './index'
@@ -271,6 +341,8 @@ const model = {
271341
export default model
272342
```
273343

344+
[⇧ back to top](#table-of-contents)
345+
274346
### subscribe
275347

276348
subscribe(storeName, actions, callback) run the callback when the specific actions executed.
@@ -307,7 +379,7 @@ TypeScript Example
307379
// StateType and ActionsParamType definition
308380
// ...
309381

310-
const Model: ModelType<StateType, ActionsParamType> = {
382+
const model: NextModelType<StateType, ActionsParamType> = {
311383
actions: {
312384
increment: async (s, _, params) => {
313385
// issue: https://github.com/Microsoft/TypeScript/issues/29196
@@ -321,6 +393,8 @@ const Model: ModelType<StateType, ActionsParamType> = {
321393
}
322394
}
323395
}
396+
397+
export default Model(model)
324398
```
325399

326400
JavaScript Example
@@ -350,9 +424,9 @@ const initialState = {
350424
counter: 0
351425
}
352426

353-
const Model: ModelType<StateType, ActionsParamType> = {
427+
const model: NextModelType<StateType, ActionsParamType> = {
354428
actions: {
355-
increment: (state, _, params) => {
429+
increment: (params, { state }) => {
356430
return {
357431
counter: state.counter + (params || 1)
358432
}
@@ -365,6 +439,8 @@ const Model: ModelType<StateType, ActionsParamType> = {
365439
},
366440
state: initialState
367441
}
442+
443+
export default Model(model)
368444
```
369445

370446
</p>

src/index.tsx

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ function Model<M extends Models, MT extends NextModelType>(
2828
initialState?: Global['State']
2929
) {
3030
if (isNextModelType(models)) {
31+
Global.uid += 1
3132
const hash = '__' + Global.uid
3233
Global.State[hash] = models.state
3334
const nextActions: Actions = Object.entries(models.actions).reduce(
@@ -163,17 +164,19 @@ const getActions = (
163164

164165
const useStore = (modelName: string, depActions?: string[]) => {
165166
const setState = useState(Global.State[modelName])[1]
166-
Global.uid += 1
167-
const hash = '' + Global.uid
168-
if (!Global.Setter.functionSetter[modelName]) {
169-
Global.Setter.functionSetter[modelName] = {}
170-
}
171-
Global.Setter.functionSetter[modelName][hash] = { setState, depActions }
167+
172168
useEffect(() => {
169+
Global.uid += 1
170+
const hash = '' + Global.uid
171+
if (!Global.Setter.functionSetter[modelName]) {
172+
Global.Setter.functionSetter[modelName] = {}
173+
}
174+
Global.Setter.functionSetter[modelName][hash] = { setState, depActions }
173175
return function cleanup() {
174176
delete Global.Setter.functionSetter[modelName][hash]
175177
}
176-
})
178+
}, [])
179+
177180
const updaters = getActions(modelName, { setState, type: 'function' })
178181
return [getState(modelName), updaters]
179182
}

0 commit comments

Comments
 (0)