Skip to content

Commit 8833e97

Browse files
alvinhuiluhc228
andauthored
Release 1.3.4 (#96)
* chore: model validate show name * fix: fix can't get correct state (#95) * fix: fix can't get correct state * chore: update version * fix: fix by the comment * docs: readonly && get the latest state Co-authored-by: Hengchang Lu <44047106+luhc228@users.noreply.github.com>
1 parent 41586a8 commit 8833e97

File tree

7 files changed

+200
-49
lines changed

7 files changed

+200
-49
lines changed

docs/recipes.md

Lines changed: 95 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,81 @@ For example, the action A in Model A calls the action B in Model B and the actio
6767

6868
Be careful the possibility of endless loop problem will arise when methods from different models call each other.
6969

70+
## Readonly
71+
72+
In some scenarios, you may only want to call the method returned by the model to update the state instead of subscribing to the update of the model state. For example, the button component in the "Basic example", you do not consume the state of the model in the component, so you may not expect the change of the state of the model to trigger the re-rende of the component.
73+
74+
At this time, you can use the `useModelDispatchers` API, check following example:
75+
76+
```js
77+
import store from '@/store';
78+
const { useModelDispatchers } = store;
79+
function Button() {
80+
const [, dispatchers ] = useModel('counter'); // The update of model'state will be subscribed here
81+
const { increment } = dispatchers;
82+
return (
83+
<button type="button" onClick={increment}> + </button>
84+
);
85+
}
86+
87+
function Button() {
88+
const { increment } = useModelDispatchers('counter'); // Updates to model'state will not be subscribed here
89+
return (
90+
<button type="button" onClick={increment}> + </button>
91+
);
92+
}
93+
```
94+
95+
## Get the latest sate of the model
96+
97+
In some scenarios, you may want to get the latest state of the model.
98+
99+
### In Component
100+
101+
```js
102+
import store from '@/store';
103+
104+
function Logger({ foo }) {
105+
// case 1 use state only instead of subscribing to updates(a means of performance optimization)
106+
function doSomeThing() {
107+
const counter = store.getModelState('counter');
108+
alert(counter);
109+
};
110+
111+
112+
// case 2 get the latest state in the closure
113+
const doOhterThing = useCallback(
114+
(payload) => {
115+
const counter = store.getModelState('counter');
116+
alert(counter + foo);
117+
},
118+
[foo]
119+
);
120+
121+
return (
122+
<div>
123+
<button onClick={doSomeThing}>click 1<button>
124+
<button onClick={doOhterThing}>click 2<button>
125+
</div>
126+
);
127+
}
128+
```
129+
130+
### In Model
131+
132+
```js
133+
import store from '@/store';
134+
135+
const user = {
136+
effects: dispatch => ({
137+
async addByAsync(payload, state) {
138+
dispatch.todos.addTodo(payload); // Call methods of other models to update their state
139+
const todos = store.getModelState('todos'); // Get the latest state of the updated model
140+
}
141+
})
142+
}
143+
```
144+
70145
## effects' executing status
71146

72147
`icestore` has built-in support to access the executing status of effects. This enables users to have access to the isLoading and error executing status of effects without defining extra state, making the code more consise and clean.
@@ -161,26 +236,6 @@ You can use `withModelDispatchers` to call only model actions without listening
161236

162237
See [docs/api](./api.md) for more details.
163238

164-
## Directory organization
165-
166-
For most small and medium-sized projects, it is recommended to centrally manage all the project models in the global `src/models/` directory:
167-
168-
```bash
169-
├── src/
170-
│ ├── components/
171-
│ │ └── NotFound/
172-
│ ├── pages/
173-
│ │ └── Home
174-
│ ├── models/
175-
│ │ ├── modelA.js
176-
│ │ ├── modelB.js
177-
│ │ ├── modelC.js
178-
│ │ └── index.js
179-
│ └── store.js
180-
```
181-
182-
If the project is relatively large, or more likely to follow the page maintenance of the store,then you can declare a store instance in each page directory. However, in this case, cross page store calls should be avoided as much as possible.
183-
184239
## Immutable Description
185240

186241
### Don't destructure the state argument
@@ -234,6 +289,26 @@ const store = createStore(models, {
234289
});
235290
```
236291

292+
## Directory organization
293+
294+
For most small and medium-sized projects, it is recommended to centrally manage all the project models in the global `src/models/` directory:
295+
296+
```bash
297+
├── src/
298+
│ ├── components/
299+
│ │ └── NotFound/
300+
│ ├── pages/
301+
│ │ └── Home
302+
│ ├── models/
303+
│ │ ├── modelA.js
304+
│ │ ├── modelB.js
305+
│ │ ├── modelC.js
306+
│ │ └── index.js
307+
│ └── store.js
308+
```
309+
310+
If the project is relatively large, or more likely to follow the page maintenance of the store,then you can declare a store instance in each page directory. However, in this case, cross page store calls should be avoided as much as possible.
311+
237312
## Comparison
238313

239314
- O: Yes

docs/recipes.zh-CN.md

Lines changed: 96 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,81 @@ export default createStore({
6565

6666
如果是多个模型间进行相互调用,死循环问题的出现概率就会提升。
6767

68+
69+
## 只调用方法而不订阅更新
70+
71+
在某些场景下,您可能只希望调用模型方法来更新状态而不订阅模型状态的更新。 例如「快速开始」示例中的 Button 组件,您没有在组件中消费模型的状态,因此可能不期望模型状态的变化触发组件的重新渲染。 这时候您可以使用 useModelDispatchers API,看下面的示例比较:
72+
73+
```js
74+
import store from '@/store';
75+
76+
const { useModelDispatchers } = store;
77+
function Button() {
78+
const [, dispatchers ] = useModel('counter'); // 这里会订阅模型状态的更新
79+
const { increment } = dispatchers;
80+
return (
81+
<button type="button" onClick={increment}> + </button>
82+
);
83+
}
84+
85+
function Button() {
86+
const { increment } = useModelDispatchers('counter'); // 这里不会订阅模型状态的更新
87+
return (
88+
<button type="button" onClick={increment}> + </button>
89+
);
90+
}
91+
```
92+
93+
## 获取模型最新状态
94+
95+
在某些场景下,您可能需要获取到模型的最新状态。
96+
97+
### 在组件中
98+
99+
```js
100+
import store from '@/store';
101+
102+
function Logger({ foo }) {
103+
// case 1 只使用状态而不订阅更新(性能优化的手段)
104+
function doSomeThing() {
105+
const counter = store.getModelState('counter');
106+
alert(counter);
107+
};
108+
109+
110+
// case 2 在闭包中获取最新状态
111+
const doOhterThing = useCallback(
112+
(payload) => {
113+
const counter = store.getModelState('counter');
114+
alert(counter + foo);
115+
},
116+
[foo]
117+
);
118+
119+
return (
120+
<div>
121+
<button onClick={doSomeThing}>click 1<button>
122+
<button onClick={doOhterThing}>click 2<button>
123+
</div>
124+
);
125+
}
126+
```
127+
128+
### 在模型中
129+
130+
```js
131+
import store from '@/store';
132+
133+
const user = {
134+
effects: dispatch => ({
135+
async addByAsync(payload, state) {
136+
dispatch.todos.addTodo(payload); // 调用其他模型的方法更新其状态
137+
const todos = store.getModelState('todos'); // 获取更新后的模型最新状态
138+
}
139+
})
140+
}
141+
```
142+
68143
## 模型副作用的执行状态
69144

70145
icestore 内部集成了对于异步副作用的状态记录,方便您在不增加额外的状态的前提下访问异步副作用的执行状态(loading 与 error),从而使状态渲染的处理逻辑更加简洁。
@@ -159,26 +234,6 @@ export default compose(withModel('user'), withModel('todos'))(TodoList);
159234

160235
查看 [docs/api](./api.zh-CN.md) 了解其使用方式。
161236

162-
## 项目的目录组织
163-
164-
对于大多数中小型项目,建议集中管理模型,例如在 “src/models/” 目录中存放项目的所有模型:
165-
166-
```bash
167-
├── src/
168-
│ ├── components/
169-
│ │ └── NotFound/
170-
│ ├── pages/
171-
│ │ └── Home
172-
│ ├── models/
173-
│ │ ├── modelA.js
174-
│ │ ├── modelB.js
175-
│ │ ├── modelC.js
176-
│ │ └── index.js
177-
│ └── store.js
178-
```
179-
180-
如果项目相对较大,可以按照页面来管理模型。但是,在这种情况下,应该避免跨页面使用模型。
181-
182237
## 可变状态的说明
183238

184239
icestore 默认为 reducer 提供了状态可变的操作方式。
@@ -231,6 +286,27 @@ const store = createStore(models, {
231286
disableImmer: true; // 👈 通过该配置禁用 immer
232287
});
233288
```
289+
290+
## 项目的目录组织
291+
292+
对于大多数中小型项目,建议集中管理模型,例如在 “src/models/” 目录中存放项目的所有模型:
293+
294+
```bash
295+
├── src/
296+
│ ├── components/
297+
│ │ └── NotFound/
298+
│ ├── pages/
299+
│ │ └── Home
300+
│ ├── models/
301+
│ │ ├── modelA.js
302+
│ │ ├── modelB.js
303+
│ │ ├── modelC.js
304+
│ │ └── index.js
305+
│ └── store.js
306+
```
307+
308+
如果项目相对较大,可以按照页面来管理模型。但是,在这种情况下,应该避免跨页面使用模型。
309+
234310
## 能力对比表
235311

236312
- O: 支持

examples/counter/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"version": "1.0.0",
44
"private": true,
55
"dependencies": {
6-
"@ice/store": "^1.3.3",
6+
"@ice/store": "^1.3.4",
77
"react": "^16.8.6",
88
"react-dom": "^16.8.6"
99
},
@@ -31,4 +31,4 @@
3131
"last 1 safari version"
3232
]
3333
}
34-
}
34+
}

examples/todos/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"version": "1.0.0",
44
"private": true,
55
"dependencies": {
6-
"@ice/store": "^1.3.3",
6+
"@ice/store": "^1.3.4",
77
"lodash": "^4.17.15",
88
"react": "^16.8.6",
99
"react-dom": "^16.8.6"
@@ -33,4 +33,4 @@
3333
"last 1 safari version"
3434
]
3535
}
36-
}
36+
}

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@ice/store",
3-
"version": "1.3.3",
3+
"version": "1.3.4",
44
"description": "Simple and friendly state for React",
55
"main": "lib/index.js",
66
"files": [
@@ -64,4 +64,4 @@
6464
"redux": "^4.0.5",
6565
"redux-thunk": "^2.3.0"
6666
}
67-
}
67+
}

src/icestore.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,12 @@ export default class Icestore {
5555
[typeof model.name !== 'string', 'model "name" [string] is required'],
5656
[
5757
model.state === undefined && model.baseReducer === undefined,
58-
'model "state" is required',
58+
`model(${model.name}) "state" is required`,
5959
],
6060
[
6161
model.baseReducer !== undefined &&
6262
typeof model.baseReducer !== 'function',
63-
'model "baseReducer" must be a function',
63+
`model(${model.name}) "baseReducer" must be a function`,
6464
],
6565
]);
6666
// run plugin model subscriptions

src/plugins/modelApis.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export default (): T.Plugin => {
2121
}
2222
function useModelState(name: string) {
2323
const selector = store.useSelector(state => state[name]);
24-
if (selector) {
24+
if (typeof selector !== "undefined") {
2525
return selector;
2626
}
2727
throw new Error(`Not found model by namespace: ${name}.`);

0 commit comments

Comments
 (0)