1. 首页

使用React Hook实现Redux状态机

Redux is a predictable state container for JavaScript apps.

原文地址:使用React Hook实现Redux状态机

本文的代码可以在CodeSandbox中查看。

Redux是React经常用到的一个数据状态管理器(状态机),它将应用中所有的数据(state)以对象树的形式存储在store中,通过触发action来改变state,而描绘改变规则需要编写reducer

因为Redux不仅仅是为React编写的,所以在React中常常会用到React-Redux来一同使用。React-Redux使用两个主要的API,分为叫做Providerconnect来提升Redux开发效率和体验。

在React 16.8之前,为了实现统一的状态机,最好的方法就是使用Redux了。不过,React 16.8中Hook API新增的useContextuseReducer能够让我们自己实现一个具备Redux核心功能的状态机。

我们先看一下Redux的三个基本原则是什么:

  1. 单一数据源 – 整个应用程序的state存储在单个store的对象树中
  2. state为只读 – 改变state的唯一方法是触发一个action
  3. 使用纯函数来修改 – 为了描述actions是如何修改state,你需要编写reducers

我们遵循这三个基本原则来开发我们自己的状态机,其实查看useReducer的用法就知道它已经满足了原则2和3

const [state, dispatch] = useReducer(reducer, initialArg, init);

所以,我们结合官网的例子来编写statereducer

文件目录如下所示:


public src reducer index.js index.js style.css package.json

在reducer文件夹的index.js文件中,编写initialStatereducer


export const initialState = { count: 0 }; export function reducer(state, action) { switch (action.type) { case "increment": return { count: state.count + 1 }; case "decrement": return { count: state.count - 1 }; default: throw new Error(); } }

然后在src/index.js中生成一个store,只在顶层组件中创建一个store是为了符合原则1。


import { reducer, initialState } from "./reducer"; const store = useReducer(reducer, initialState);

可以看到应用useReducer很简单的就创建了一个符合Redux三个基本原则的状态机,然后我们就要考虑如何将store状态传递到更深层次的组件中。在Redux中我们使用subscribe方法去订阅状态,而使用React-Redux可以将store像props一样传值给子组件,这样就不需要每次都去订阅。所以,接下来我们使用React中的Context API来实现状态的传递。

在src/index.js中创建一个AppContext,初始值为空:


const AppContext = createContext({}); const { Provider } = AppContext;

然后在顶层组件App中使用:


function App() { const store = useReducer(reducer, initialState); return ( <Provider value={store}> <div className="App"> <TopNavBar /> </div> </Provider> ); }

这样无论多深的组件都能够获取到store存储的数据状态,而且能够获取到dispatch方法来改变state。这里React的另一个Hook就要发挥实力了,那就是useContext,它可以接收一个context对象(React.createContext的返回值)并返回该context的当前值。


function TopNavBar() { const value = useContext(AppContext); const [state] = value; // 这里的value就是useReducer创建的store const { count } = state; return ( <> <p>{count}</p> <Button /> </> ); }

Button组件中使用useContext获取dispatch来通过触发一个action来改变count的值:


function Button() { const value = useContext(AppContext); const [state, dispatch] = value; return ( <div className="button-wrapper"> <button type="button" onClick={() => dispatch({ type: "increment" })}> Plus </button> <button type="button" onClick={() => dispatch({ type: "decrement" })}> Minus </button> </div> ); }

这样一个满足Redux的三个原则,同时具备React-Redux部分功能的简洁版状态机就完成了。在一些不需要管理过多复杂状态的应用中我们就可以使用这样的方式来自己创建状态机,当然,我们还有像effectconnectmiddleware这样的功能没有完全实现,但是在准备使用他们之前,先得思考以下,是否真的需要。

Brevity is the soul of wisdom. Tediousness is the limbs and outward flourishes.

—— William Shakespeare

作者:xiangjun
链接:https://juejin.im/post/5d7b78456fb9a06af92bd12e

看完两件小事

如果你觉得这篇文章对你挺有启发,我想请你帮我两个小忙:

  1. 关注我们的 GitHub 博客,让我们成为长期关系
  2. 把这篇文章分享给你的朋友 / 交流群,让更多的人看到,一起进步,一起成长!
  3. 关注公众号 「画漫画的程序员」,公众号后台回复「资源」 免费领取我精心整理的前端进阶资源教程

JS中文网是中国领先的新一代开发者社区和专业的技术媒体,一个帮助开发者成长的社区,目前已经覆盖和服务了超过 300 万开发者,你每天都可以在这里找到技术世界的头条内容。欢迎热爱技术的你一起加入交流与学习,JS中文网的使命是帮助开发者用代码改变世界

本文著作权归作者所有,如若转载,请注明出处

转载请注明:文章转载自「 Js中文网 · 前端进阶资源教程 」https://www.javascriptc.com

标题:使用React Hook实现Redux状态机

链接:https://www.javascriptc.com/3838.html

« 从写一个分页表格来讲讲react hook怎么玩
通过事例重温一下常见的 JS 中 15 种数组操作(备忘清单)»
Flutter 中文教程资源

相关推荐

QR code