# @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>
}
```
