Skip to content

Commit 846e340

Browse files
committed
feat(usemodel): make useModel api the same as useState
1 parent f61afdd commit 846e340

File tree

3 files changed

+82
-44
lines changed

3 files changed

+82
-44
lines changed

__test__/lane/lane.spec.ts

+26
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,32 @@ describe('lane model', () => {
2929
})
3030
})
3131

32+
test('pass function to useModel ', async () => {
33+
const { useStore } = createStore(() => {
34+
const [count, setCount] = useModel(() => 1)
35+
return { count, setCount }
36+
})
37+
let renderTimes = 0
38+
const { result } = renderHook(() => {
39+
const { count, setCount } = useStore()
40+
renderTimes += 1
41+
return { renderTimes, count, setCount }
42+
})
43+
await act(async () => {
44+
expect(renderTimes).toEqual(1)
45+
expect(result.current.count).toBe(1)
46+
})
47+
48+
await act(async () => {
49+
await result.current.setCount((count) => count + 1)
50+
})
51+
52+
await act(() => {
53+
expect(renderTimes).toEqual(2)
54+
expect(result.current.count).toBe(2)
55+
})
56+
})
57+
3258
test('false value can be accepted', async () => {
3359
const { useStore } = createStore(() => {
3460
const [count, setCount] = useModel(true)

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-model",
3-
"version": "4.1.0-alpha.1",
3+
"version": "4.1.0-alpha.2",
44
"description": "The State management library for React",
55
"main": "./dist/react-model.js",
66
"module": "./dist/react-model.esm.js",

src/index.tsx

+55-43
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,22 @@ const isAPI = (input: any): input is API => {
2323

2424
// useModel rules:
2525
// DON'T USE useModel OUTSIDE createStore func
26-
function useModel<S>(state: S): [S, (state: S) => void] {
26+
function useModel<S>(
27+
state: S | (() => S)
28+
): [S, (state: S | ((state: S) => S)) => void] {
2729
const storeId = Global.currentStoreId
2830
const index = Global.mutableState[storeId].count
2931
Global.mutableState[storeId].count += 1
3032
if (!Global.mutableState[storeId].hasOwnProperty(index)) {
31-
Global.mutableState[storeId][index] = state
33+
if (typeof state === 'function') {
34+
// @ts-ignore
35+
Global.mutableState[storeId][index] = state()
36+
} else {
37+
Global.mutableState[storeId][index] = state
38+
}
3239
}
3340

34-
const setter = async (state: S) => {
41+
const setter = async (state: S | ((prevState: S) => S)) => {
3542
const context: InnerContext = {
3643
Global,
3744
action: () => {
@@ -46,7 +53,16 @@ function useModel<S>(state: S): [S, (state: S) => void] {
4653
params: undefined,
4754
type: 'useModel'
4855
}
49-
Global.mutableState[storeId][index] = state
56+
57+
if (typeof state === 'function') {
58+
// @ts-ignore
59+
Global.mutableState[storeId][index] = state(
60+
Global.mutableState[storeId][index]
61+
)
62+
} else {
63+
Global.mutableState[storeId][index] = state
64+
}
65+
// pass update event to other components subscribe the same store
5066
return await applyMiddlewares(actionMiddlewares, context)
5167
}
5268
return [Global.mutableState[storeId][index], setter]
@@ -124,11 +140,9 @@ function Model<M extends Models, MT extends ModelType, E>(
124140
} else {
125141
if (models.actions) {
126142
console.error('invalid model(s) schema: ', models)
127-
const errorFn =
128-
(fakeReturnVal?: unknown) =>
129-
(..._: unknown[]) => {
130-
return fakeReturnVal
131-
}
143+
const errorFn = (fakeReturnVal?: unknown) => (..._: unknown[]) => {
144+
return fakeReturnVal
145+
}
132146
// Fallback Functions
133147
return {
134148
__ERROR__: true,
@@ -325,41 +339,39 @@ class Provider extends PureComponent<{}, Global['State']> {
325339
}
326340
}
327341

328-
const connect =
329-
(
330-
modelName: string,
331-
mapState?: Function | undefined,
332-
mapActions?: Function | undefined
333-
) =>
334-
(Component: typeof React.Component | typeof PureComponent) =>
335-
class P extends PureComponent<any> {
336-
render() {
337-
const { state: prevState = {}, actions: prevActions = {} } = this.props
338-
return (
339-
<Consumer>
340-
{(models) => {
341-
const { [`${modelName}`]: state } = models as any
342-
const actions = Global.Actions[modelName]
343-
return (
344-
<Component
345-
{...this.props}
346-
state={{
347-
...prevState,
348-
...(mapState ? mapState(state) : state)
349-
}}
350-
actions={{
351-
...prevActions,
352-
...(mapActions
353-
? mapActions(consumerActions(actions, { modelName }))
354-
: consumerActions(actions, { modelName }))
355-
}}
356-
/>
357-
)
358-
}}
359-
</Consumer>
360-
)
361-
}
342+
const connect = (
343+
modelName: string,
344+
mapState?: Function | undefined,
345+
mapActions?: Function | undefined
346+
) => (Component: typeof React.Component | typeof PureComponent) =>
347+
class P extends PureComponent<any> {
348+
render() {
349+
const { state: prevState = {}, actions: prevActions = {} } = this.props
350+
return (
351+
<Consumer>
352+
{(models) => {
353+
const { [`${modelName}`]: state } = models as any
354+
const actions = Global.Actions[modelName]
355+
return (
356+
<Component
357+
{...this.props}
358+
state={{
359+
...prevState,
360+
...(mapState ? mapState(state) : state)
361+
}}
362+
actions={{
363+
...prevActions,
364+
...(mapActions
365+
? mapActions(consumerActions(actions, { modelName }))
366+
: consumerActions(actions, { modelName }))
367+
}}
368+
/>
369+
)
370+
}}
371+
</Consumer>
372+
)
362373
}
374+
}
363375

364376
export {
365377
actionMiddlewares,

0 commit comments

Comments
 (0)