zoukankan      html  css  js  c++  java
  • React Hooks useContext + useReducer实现简易Redux

    context api是简化版的redux,他没有redux强大生态体系,结合各自中间件例如thunk或saga,做data fetching或处理side effect,不过单单想存一些share data避免props drilling的问题却绰绰有余。

    • context 提供了一个无需为每层组件手动添加 props,就能在组件树间进行数据传递的方法
    • reducer 应是纯函数,根据旧的状态和新的参数计算出最新的状态,其中新的参数来自于 dispatch(新的参数)

    所以使用 context 还是 redux 要看需求、看成本、看以后拓展性、可维护性。(react-redux 从 v7.1.0开始也提供了 hooks api 以减少繁琐的高阶组件嵌套)

    跟着 React 官网文档,首先去看 高级指引-Context,重点理解 React.createContext(initialValue) 方法返回的 Provider 和 Consumer 组件,这是生产者和消费者模型。

    知道 context 在函数式组件中基本用法后,去看 useContext,重点去感受使用了 useContext 后,代替了之前 <MyContext.Consumer> 这种写法,令 Context 的引用变得更加方便。

    接下来假设你本身已经使用过 Redux,对 Redux 那一套流程有基本的了解,Redux 本身是可以脱离 React 运行的,这是个用于全局状态管理的库,你当然可以结合 JQuery 来使用,但目前来看,之所以这么流行,还是因为结合了 React,所以 Redux 在 React 中主要依赖了 react-redux 这个库。

    跟着 React 官方文档,了解 useReducer 的用法,这里也提供了 useReducer 的大概原理。

    相信我,尽管可能先从其他地方开始学习 hooks,但是官方文档绝对不要错过。

    我们模拟类似 redux 的功能,简单分为三步:

    1. 使用 useReducer 在根组件创建需要共享的 state 和用来更新它的 dispatch()
    2. 使用 context api 把刚才的 state 和 dispatch 同时共享下去
    3. 使用 useContext 方便底层组件读写共享的 state
    import React, { useContext, useReducer } from 'react';
    
    const BankContext = React.createContext({});
    
    // 和 redux 一样,综合根据旧 state 和 dispatch 而来的数据,计算出最新的 state
    function reducer(state, action) {
      switch (action.type) {
        case 'deposit':
          return { balance: state.balance + action.payload };
        default:
          throw new Error();
      }
    }
    
    // 纯粹为了展示 useReducer 第三个参数
    function init(initialCount) {
      return { balance: initialCount };
    }
    
    // 根组件
    export default function App() {
      const [state, dispatch] = useReducer(reducer, 0, init);
      return (
        <BankContext.Provider value={{
          state,
          dispatch // 把 dispatch 也作为 context 的一部分共享下去,从而在嵌套组件中调用以实现更新顶层的 state
        }}>
          <Layout>
            <Content />
          </Layout>
        </BankContext.Provider>
      );
    }
    
    // 子组件
    function Layout(props) {
      return (
        <div style={{ border: '5px solid lightblue', padding: '20px' }}>
          <p>您就当我是个 Layout 组件吧!</p>
          {props.children}
        </div>
      );
    }
    
    // 孙组件
    // 经过层层嵌套后,可以在孙组件中读取全局 state 并设置
    function Content() {
      // 这里不要误会,useContext(BankContext) 返回值就是我们共享出来的 context,
      // 只是这里刻意把 context 设计为对象,以便同时提供 dispatch
      const { state, dispatch } = useContext(BankContext);
      return (
        <div style={{ border: '1px solid #666' }}>
          <div> 当前余额:{state.balance}</div>
          <button onClick={() => dispatch({ type: 'deposit', payload: 100 })}>存入100元</button>
        </div>
      );
    }
    
  • 相关阅读:
    ROS Learning-013 beginner_Tutorials (编程) 编写ROS服务版的Hello World程序(Python版)
    ROS Learning-012 beginner_Tutorials (编程) 创建自定义的ROS消息和ROS服务
    电子模块 001 --- 遥杆 JoyStick
    ROS Learning-011 beginner_Tutorials (编程) 编写 ROS 话题版的 Hello World 程序(Python版)
    STM32 C++编程 002 GPIO类
    Python 网络爬虫 002 (入门) 爬取一个网站之前,要了解的知识
    STM32 C++编程 001 工程模板
    ROS Learning-010 beginner_Tutorials 编写简单的启动脚本文件(.launch 文件)
    Python 网络爬虫 001 (科普) 网络爬虫简介
    Python 黑客 --- 002 入门级 ZIP压缩文件口令暴力破解机
  • 原文地址:https://www.cnblogs.com/nicholaswang/p/11887013.html
Copyright © 2011-2022 走看看