阅读 324

如何用useContext + useReducer实现redux功能

Redux开发步骤

在hooks没有出来之前,Redux毫无疑问是众多React项目首选的状态管理方案,在项目创建之前,需要做好文件夹分割。

Redux三要素:(个人理解)

  • Action: 存储函数方法
  • Store: 存储数据的仓库
  • Reducer: 数据处理仓库,必须是纯函数

文件夹

  • actons(放置函数方法)export const pullGroupList = (data) => ({type: types.GROUPLIST_PULL, data })
  • constants (放置函数方法的type类型 ActionTypes.js) export const GROUPLIST_PULL = 'GROUPLIST_PULL'
  • reducers (放置数据处理纯函数)
  • containers (引入actons,创建connect HOC,新增mapStateToProps 和 mapDispatchToProps两个方法)

新增步骤

在已经构建好的项目的前提下:

  1. ActionTypes中新增type
  2. actons中新增函数方法
  3. reducers中新增reducer.js,书写数据处理纯函数,并通过combineReducer 和并 reduce
  4. containers中新增js,将 action 引入到组件中,通过 connect HOC 与你的组件相连,增加两个方法 mapStateToProps 和 mapDispatchToProps

useContext + useReducer

hooks出现之后,可以用useContext+useReducer实现redux状态管理功能,因此写了个小demo

但是有更高的要求,如下:

使用useContext+useReducer做一个类似react-redux来管理状态 - 输出一个Provider 组件,接收全局store - 输出一个connect函数,接收mapStateToProps,mapDispatchToProps两个方法返回一个connectHoc高阶组件(属性代理方式将store 的值传递到组件的props里)

然后就发现不会了😢

  1. 怎么输出一个Provider 组件,接收全局store?目前的store还是用redux的import { createStore, applyMiddleware, compose } from 'redux'
  2. 怎么输出一个connect函数,接收mapStateToProps,mapDispatchToProps?目前用的也还是redux的import {bindActionCreators} from "redux";import {connect} from "react-redux";
  3. 多个reducer时,该怎么整合?目前使用import { combineReducers } from 'redux'

只会简单的应用,不知道该怎么统一代码了。

搜索到的答案:

  1. 可以参考 redux 写一个CombineReducer, 用 Array.prototype.reduce 很好实现。
  2. 把 Provider 写到最外层组件就可以实现全局共享。
  3. store 属于哪个组件就写到哪个组件里面。

求教,最好是有代码的那种~

2019/12/02 解法:

输出一个Provider 组件,接收全局store

const Store = createContext();

export default function ReactApp() {
    const [state, dispatch] = useReducer(reducer, {count: 0, step: 0})

    return ( 
        <Store.Provider value={{state, dispatch}}>
            <Count/>
            <Step/>
        </Store.Provider>)
}

const Count = () => {
    const {state, dispatch} = useContext(Store)
    return useMemo(()=>(
        <Button onClick={() => dispatch({type: 'incCount'})}>incCount {state.count}</Button>
    ),[state.count,dispatch])
}
复制代码
  1. createContext()创建一个全局store;
  2. Store.Provider实现store的传递;
  3. useContext(Store)使用全局store

useMemo 相似于一个connect函数 对比一下 Connect 与 useMemo,会发现惊人的相似之处。

一个普通的 Redux 组件:

const mapStateToProps = state => (count: state.count);

const mapDispatchToProps = dispatch => dispatch;



class Count extends React.PureComponent {
  render() {
    return (
      <button onClick={() => this.props.dispatch("incCount")}>
        incCount {this.props.count}
      </button>
    );
  }
}

export default Connect(
    mapStateToProps,
    mapDispatchToProps
)(Count)
复制代码

一个普通的 Function Component 组件:

const Count = () => {
  const { state, dispatch } = useContext(Store);
  return useMemo(
    () => (
      <button onClick={() => dispatch("incCount")}>
        incCount {state.count}
      </button>
    ),
    [state.count, dispatch]
  );
};
复制代码