Skip to content

Commit ec0111d

Browse files
committed
feat(migrate): support old model migration
1 parent 7342bf4 commit ec0111d

File tree

3 files changed

+159
-11
lines changed

3 files changed

+159
-11
lines changed

README.md

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ npm install react-model
8383
- [Provider](#provider)
8484
- [connect](#connect)
8585
- [FAQ](#faq)
86+
- [Migrate from 4.0.x to 4.1.x](#migrate-from-40x-to-41x)
8687
- [Migrate from 3.1.x to 4.x.x](#migrate-from-31x-to-4xx)
8788
- [How can I disable the console debugger?](#how-can-i-disable-the-console-debugger)
8889
- [How can I add custom middleware](#how-can-i-add-custom-middleware)
@@ -694,6 +695,77 @@ export default connect(
694695
695696
## FAQ
696697
698+
### Migrate from 4.0.x to 4.1.x
699+
700+
1. replace Model with createStore
701+
702+
`counter.ts`
703+
704+
```ts
705+
import { createStore } from 'react-model'
706+
// Remove typedef below
707+
// type CounterState = {
708+
// count: number
709+
// }
710+
711+
// type CounterActionParams = {
712+
// increment: number
713+
// }
714+
715+
// v4.0.x model
716+
const Counter: ModelType<
717+
CounterState,
718+
CounterActionParams
719+
> = {
720+
actions: {
721+
increment: (params) => {
722+
return (state) => {
723+
state.count += params
724+
}
725+
}
726+
},
727+
state: { count: 0 }
728+
}
729+
730+
// v4.1.x
731+
const Counter = createStore(() => {
732+
const [state, setState] = useModel({ count: 0 })
733+
const actions = {
734+
increment: (params) => {
735+
setState((state) => {
736+
state.count += params
737+
})
738+
}
739+
}
740+
return [state, actions]
741+
})
742+
743+
export default Counter
744+
```
745+
746+
2. Remove Counter from model registry
747+
748+
```ts
749+
const models = {
750+
// Counter
751+
Shared
752+
}
753+
754+
export const { getInitialState, useStore, getState, actions, subscribe, unsubscribe } = Model(models)
755+
```
756+
757+
3. update useStore calls in components
758+
759+
```tsx
760+
// import { useStore } from 'models'
761+
import Counter from 'models/counter'
762+
763+
const Component = () => {
764+
// const [state, actions] = useStore('Counter')
765+
const [state, actions] = Counter.useStore()
766+
}
767+
```
768+
697769
### Migrate from 3.1.x to 4.x.x
698770
699771
1. remove Model wrapper

__test__/lane/migrate.spec.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/// <reference path="../index.d.ts" />
2+
import { renderHook, act } from '@testing-library/react-hooks'
3+
import { createStore, useModel } from '../../src'
4+
import { timeout } from '../../src/helper'
5+
// import { timeout } from '../../src/helper'
6+
7+
describe('migrate test', async () => {
8+
test('migrate from v4.0.x', async () => {
9+
const store = createStore(() => {
10+
const [state, setState] = useModel({ count: 0, otherKey: 'key' })
11+
const actions = {
12+
add: (params: number) => {
13+
return setState({
14+
count: state.count + params
15+
})
16+
},
17+
addCaller: () => {
18+
actions.add(5)
19+
},
20+
increment: (params: number) => {
21+
return setState((state) => {
22+
state.count += params
23+
})
24+
}
25+
}
26+
return [state, actions] as const
27+
})
28+
29+
let renderTimes = 0
30+
31+
const { result } = renderHook(() => {
32+
renderTimes += 1
33+
const [state, actions] = store.useStore()
34+
return { state, renderTimes, actions }
35+
})
36+
37+
act(() => {
38+
expect(result.current.renderTimes).toEqual(1)
39+
expect(result.current.state.count).toBe(0)
40+
})
41+
42+
act(() => {
43+
result.current.actions.addCaller()
44+
})
45+
46+
act(() => {
47+
expect(renderTimes).toEqual(2)
48+
expect(result.current.state.count).toBe(5)
49+
expect(result.current.state.otherKey).toBe('key')
50+
})
51+
52+
act(() => {
53+
result.current.actions.increment(5)
54+
})
55+
56+
await timeout(300, {})
57+
58+
act(() => {
59+
// expect(renderTimes).toEqual(3)
60+
console.group('expect result.current.state.count')
61+
expect(result.current.state.count).toBe(10)
62+
})
63+
})
64+
})

src/index.tsx

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ const isAPI = (input: any): input is API => {
2626
// DON'T USE useModel OUTSIDE createStore func
2727
function useModel<S>(
2828
state: S | (() => S)
29-
): [S, (state: S | ((state: S) => S)) => void] {
29+
): [S, (state: Partial<S> | ((state: S) => S | void)) => void] {
3030
const storeId = Global.currentStoreId
3131
const index = Global.mutableState[storeId].count
3232
Global.mutableState[storeId].count += 1
@@ -39,13 +39,33 @@ function useModel<S>(
3939
}
4040
}
4141

42-
const setter = async (state: S | ((prevState: S) => S)) => {
42+
const setter = async (state: Partial<S> | ((prevState: S) => S | void)) => {
43+
if (typeof state === 'function') {
44+
Global.mutableState[storeId][index] = produce(
45+
Global.mutableState[storeId][index],
46+
// @ts-ignore
47+
state
48+
)
49+
} else {
50+
if (
51+
typeof Global.mutableState[storeId][index] === 'object' &&
52+
typeof state === 'object'
53+
) {
54+
Global.mutableState[storeId][index] = {
55+
...Global.mutableState[storeId][index],
56+
...state
57+
}
58+
} else {
59+
Global.mutableState[storeId][index] = state
60+
}
61+
}
62+
4363
const context: InnerContext = {
4464
Global,
4565
action: () => {
4666
return typeof state === 'function'
4767
? // @ts-ignore
48-
state(Global.mutableState[storeId][index])
68+
Global.mutableState[storeId][index]
4969
: state
5070
},
5171
actionName: 'setter',
@@ -58,14 +78,6 @@ function useModel<S>(
5878
type: 'u'
5979
}
6080

61-
if (typeof state === 'function') {
62-
// @ts-ignore
63-
Global.mutableState[storeId][index] = state(
64-
Global.mutableState[storeId][index]
65-
)
66-
} else {
67-
Global.mutableState[storeId][index] = state
68-
}
6981
// pass update event to other components subscribe the same store
7082
return await applyMiddlewares(actionMiddlewares, context)
7183
}

0 commit comments

Comments
 (0)