@zjxpcyc/react-tiny-store
Version:
简易版 React hook store
124 lines (82 loc) • 2.65 kB
Markdown
# @zjxpcyc/react-tiny-store
灵感来源: [@umijs/plugin-model](https://github.com/umijs/plugins/tree/master/packages/plugin-model)
## 实现原理
1. `state` 这里称为 `model` , 其实是一个 `react hook` , 书写必须符合 `react hook` 规范。
2. `model` 里面实现 `state` 的业务逻辑
3. `model` 会被挂载到内置的 `Executor` 组件
4. `useModel` 为获取 `store state` 的 `hook` 方式, `useModel` 通过 `store` 监控 `Executor` 组件的更新, 从而获取与响应最新的内容
5. `getState` 也能获取最新的 `state`, 但是不会引起组件刷新, 因为不是 `hook`
总结, `model` 是一个 `hook`, 被应用到内置组件上, `useModel` 实际上是一个新的 `hook` 用来监控内置组件的更新。
## 安装
```bash
npm install -S @zjxpcyc/react-tiny-store
```
## 使用
`react-tiny-store` 内置了一个默认 `model` , 通过 `useModel()` 可以获取到 `state`
### 1、 自定义一个 hook 作为 model
比如我需要自定义个全局的 `user`,则可以如下解决:
```javascript
import React, { useState } from 'react'
export default function useUser() {
const [user, setUser] = useState({})
const signIn = () => {
// xxx
}
const signOut = () => {
// xxx
}
return {
user,
signIn,
signOut
}
}
```
### 2、创建 APP 节点
* 把所有定义的 `model` 收集到一个 `models` 里面
```javascript
import useFoo from './useFoo'
import useBar from './useBar'
const models = {
'foo': useFoo, // 格式 namespace: hook
'bar': useBar
}
export default models
```
* 创建 `store`
```javascript
import { createStore } from '@zjxpcyc/react-tiny-store'
const store = createStore(models)
export default store
export const useModel = store.useModel
export const getState = store.getState
export const Provider = store.Provider
// store 有如下方法构成
// getState(namespace) 获取 namespace 对应的 state, 但不能引起页面重新渲染
// useModel(namespace) 其实是一个 hook, 获取 namespace 对应的 state
// Provider store 的 Provider 组件
```
* 使用 `StoreRoot`
```javascript
import { Provider } from './store'
const App = (props) => (
<Provider>
{props.children}
</Provider>
)
```
### 3、子组件调用
* 组件中使用
```javascript
import { useModel } from './store'
function Foo (props) => {
// useModel 第二个参数不传, 相当于返回整个 foo 的 state
const { foo, setFoo } = useModel('foo')
useEffect(() => {
let i = 1;
const t = setInterval(() => setFoo(i++), 1000)
return () => clearInterval(t)
}, [])
return <p>{foo}</p>
}
```