前言
大家好, react hooks出来已经有一段时间了, 相信很多热爱钻研新技术的童靴已经对react hooks有了一定的了解, 作者也是抱着发现新大陆的心态去学习并在项目中进行实践, 在这里也是和大家分享一下如何使用useReducer+useContext来实现一个简版redux。
背景
往往新特性、新技术的诞生是来自于问题的产生, 本篇文章的产生也是为了解决问题。我先前问过领导一个问题, 为什么项目中不使用redux或者mobx来作状态管理哪?
大家可以想象一下, 譬如以react为技术栈, 使用redux作为状态管理, 会遇到如下几个问题
(1)需要安装redux、react-redux、react-thunk等依赖, 依赖包变多变杂
(2)我们需要去熟悉createStore、dispatch、mapStateToProps等好多API, 这无疑大大增加了学习成本
(3)redux其实是将一整颗state树配合着方法以props的形式从根节点传递, 传递一层两层还可以, 层级如果多了, 维护起来会很吃力
既然问题出现了, 就要想着就解决问题, 那么有没有好的替代方案来解决优化上面的问题那, 当然是有的, 下面以一个表格新增删除行数据为例来手把手教大家如何使用useReducer+useContext来打造一个简版的状态管理库。[完整demo]
实践
index.js(核心代码)
useReducer
- 传递两个参数, 第一个参数是更改state状态的方法, 类似于redux的reduce, 第二个参数是初始化状态
- 返回两个参数,第一个参数为更改后的状态, 第二个参数是dispatch(用来触发更新state的操作, 类似于redux中store的dispatch)
useReducer会在页面初始化时执行一次, 此时使用到的是初始状态, 当状态更新时, 使用的是返回的dataSource, 并重新渲染
context
- 使用React.createContext({})创建context并导出使用
- 使用context.Provider, 接收一个value属性, 在这个地方可以传递任何数据, 你的dispatch、state亦或者是以对象形式传递多种数据
context的作用是提供了一种在组件之间共享此类值的方式,而不必显式地通过组件树的逐层传递 props。context小知识
reduer.js
目的是统一处理更新state
TableDemo.jsx
...
const { dispatch } = useContext(context);
dispatch({
type: types.ADD_ROW_DATA,
payload: {
key,
name: 'demo' + key,
age: 26,
address: '恒电大厦B座2层',
email: 'demo@meituan.com',
}
})
...
useContext
- 接收导出的context, useContext可以让你在任何组件中引入使用, 这里接收的参数是context实例
- 需要注意的是, 在项目中context可以是多个嵌套的
总结
使用useReducer+useContext作为状态管理, 你不需要安装额外的包(需要注意的时, react hooks是在 React@16.8新增添的功能, 请注意项目的react版本), 你也可以避免层层传递props,只需要简单地记住个别api便可以实现复杂的状态管理, 是不是很棒, 想尝试的朋友们请参照