1. 前言
2. 基本用法
2.1 providerState: 用于往 store 里面添加数据
2.2 injectState 用于把 store 里面的数据传入 UI 组件
2.3 effects 用于更改 store 里面的数据, 进行更新组件
2.4 initialState 用于定义初始状态
3. 在项目中的应用
3.1 存储共享数据
3.2 #在复杂场景下更新组件
4. 举个项目中的操作栗子
结语
1. 前言
单页应用还是需要一个状态管理器, 之前尝试过 redux, 后来觉得它的写法太繁琐了, 还需要装各种依赖, 弃之, 使用一个较为简单的 freactal.
2. 基本用法
2.1 providerState 用于往 store 里面添加数据.
- providerState({
- initialState,
- effects,
- computed,
- })
不同于 redux,freactal 可以设置多个 store, 所以 providerState 有一个特性: 在某个先加载的组件使用 providerState 提供了数据, 那么后加载的组件使用 providerState 传入一个空对象, 也可以拿到之前存入 store 里面的数据, 比如:
providerState({})
可以理解为 freactal 虽然支持书写多个 store, 但是数据的来源是唯一的, 只是写法上可以书写多个 store.js 用于区分不同的 store, 如果你不需要别的 store 里面的数据, 可以使用 injectState 进行过滤.
2.2 injectState 用于把 store 里面的数据传入 UI 组件
injectState(component, key)
key 用于筛选 store 里面的数据, 再次声明: 如果某个先加载的组件使用 providerState 往 store 里面添加的数据, 那么后加载的组件使用 providerState 也是可以拿到这些数据的, 所以通过 injectState 进行过滤你所需要的数据, 只有过滤后的数据改变, 才会触发对应的组件更新.
2.3 effects 用于更改 store 里面的数据, 进行更新组件
- const effects = {
- changeMenu: (effects, args) => mergeIntoState({currentMenu: args})
- }
args 是外部传入的参数, 比如 this.props.effects.changeMenu('/record')
mergeIntoState 相当于于 reducer, 用于更改 store 里面的数据
2.4 initialState 用于定义初始状态
- const initialState = () => ({
- active: 'hello'
- })
更多 api 请查看文档: https://github.com/FormidableLabs/freactal
3. 在项目中的应用
最初接触状态管理容器的时候直接把接口请求中的数据往 store 里面丢, 其实这是没有必要的, 而且会让代码的书写变得十分的繁琐, 于是认真思考了一下使用状态管理容器的初衷, 总结有以下几点:
3.1 存储共享数据
使用 react 开发通常会把组件细化, 当组件的层级比较多, 数据一层一层往下传递, 书写的体验就会变得十分糟糕, 在单页应用中, 这个缺点会无限放大.
如果有些数据需要在多个组件中共享, 那么请放在 store 中. 这样无论组件的层级有多深, 大家都可以使用 this.props 拿到.
3.2 在复杂场景下更新组件
比如当子孙组件需要更新祖先组件的状态, 用于显示一个 Modal, 那么代码会变成这样: 在祖先组件中定义一个方法:
- showModal = (bool) => {
- this.setState({show: bool});
- }
方法通过层层传递, 传入子孙组件中, 调用该方法
this.props.showModal(true)
代码变得十分繁琐, 也不优雅, 不如把这个状态存入 store, 当 store 中的数据改变, UI 会被更新, 兄弟组件之间数据的操作更新 UI 其实也是同理.
4. 举个项目中的操作栗子
定义 store.js
- import { mergeIntoState } from 'freactal';
- // active 为 1 是云阅读, 2 是蜗牛
- const initialState = () => ({
- active: '1',
- });
- const effects = {
- toggleRadio: (effect, args) => mergeIntoState({active: args})
- };
- export default {
- initialState,
- effects
- };
封装 withStore.js
- import { provideState, injectState } from 'freactal';
- import createLogger from 'freactal-logger';
- export default (store, keys) => (statefull) => {
- const middleware = [];
- if (process.env.NODE_ENV === 'development') {
- const logger = createLogger({
- collapsed: true
- });
- middleware.push(logger);
- }
- return provideState({
- ...store,
- middleware
- })(injectState(statefull, keys));
- }
createLogger 是一个 logger, 可以看到 store 中数据的修改
UI 组件连接 store
- import store from './store';
- import withStore from './withStore';
- @withStore(store, ['active'])
- class Result extends React.Component {}
5. 结语
react16.3.1 已经更新了新的 Context API, 操作共享数据变得十分方便了, 有空可以研究一下, 但是它并不能替代状态管理容器, 在单页的应用中, 复杂的场景下, 还是需要它.
原文连接 https://github.com/shen1992/blog/issues/14
来源: https://juejin.im/post/5ad46677f265da238c3b24c0