在react项目中使用freactal做状态管理

617 阅读3分钟
  • 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请查看文档: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,操作共享数据变得十分方便了,有空可以研究一下,但是它并不能替代状态管理容器,在单页的应用中,复杂的场景下,还是需要它。

原文连接