useReducer createContext代替Redux原理示例解析

目录
  • 前言
  • 采用react-redux实现
  • 采用react hooks模拟redux实现
  • 异步action
  • 总结

前言

最近看到很多采用useReducer + createContext 实现一个简易的redux的方案,今天亲自试了一下,发现还是会有一些区别的。

采用react-redux实现

这里使用react-redux 实现一个简单的状态管理例子。

App.jsx根组件

import React from 'react';
import { Button } from './Button';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import A from './a';
export default function ButtonDemo1() {
  const reducer = (state, action) => {
    const { name, theme } = state;
    switch (action.type) {
      case 'UPDATENAME':
        return {
          ...state,
          name: `${name} + 1`,
        };
      case 'UPDATETHEME':
        return {
          ...state,
          theme: theme === 'dark' ? 'light' : 'dark',
        };
      default:
        return state;
    }
  };
  const store = createStore(reducer, {
    name: 'fx',
    theme: 'dark',
  });
  return (
    <Provider store={store}>
      <div>
        <Button />
        <A />
      </div>
    </Provider>
  );
}

A组件用于dispatch和接收store

A.jsx

import React, { useContext } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { reduxContent } from './index1';
export default function A() {
  const dispatch = useDispatch();
  return (
    <div onClick={() => dispatch({ type: 'UPDATENAME' })}>
      {useSelector((state) => state.name)}
    </div>
  );
}

效果如图:

可以看到,Button组件未使用redux store,因此正常渲染了一次。

采用react hooks模拟redux实现

这里采用useReducer + createContext 模拟实现一个redux

App.jsx

import React, { useReducer, createContext } from 'react';
import { Button } from 'concis';
import A from './a';
export const reduxContent = createContext({});
export default function ButtonDemo1() {
  const reducer = (state, action) => {
    const { name, theme } = state;
    switch (action.type) {
      case 'UPDATENAME':
        return {
          ...state,
          name: `${name} + 1`,
        };
      case 'UPDATETHEME':
        return {
          ...state,
          theme: theme === 'dark' ? 'light' : 'dark',
        };
      default:
        return state;
    }
  };
  const [redux, dispatch] = useReducer(reducer, {
    name: 'fx',
    theme: 'dark',
  });
  return (
    <reduxContent.Provider value={{ redux, dispatch }}>
        <Button />
        <A />
    </reduxContent.Provider>
  );
}

A.jsx

import React, { useContext } from 'react';
import { reduxContent } from './index1';
export default function A() {
  const { redux, dispatch } = useContext(reduxContent);
  return (
    <div onClick={() => dispatch({ type: 'UPDATENAME' })}>
      {redux.name}
    </div>
  );
}

同样,子组件也可以对store中的状态进行getdispatch,但是会出现这样的问题:

可以看到,Button组件并没有使用store中的内容,但是会随着A组件一起跟着重新渲染,原因其实就是采用这种方式store是存储在根组件的,根组件状态发生了变化(useReducer),子组件跟着一起重新渲染了,因此解决这个问题的思路其实和解决常规的子组件没变化一起被更新的思路是一样的。

可以采用 useMemo限制 + memo 浅比较。

因此只需要在App.jsx中这样修改:

 const renderButton = React.useMemo(() => {
    return <Button />;
  }, []);
  return (
    <reduxContent.Provider value={{ redux, dispatch }}>
      <div style={{ display: 'flex', flexWrap: 'wrap' }}>
        {renderButton}
        <A />
      </div>
    </reduxContent.Provider>
  );
}

Button.jsx

const Button = (props) => {
    ......
})
export default React.memo(Button);

异步action

同样,如果需要异步dispatch的话,简单的场景其实单纯使用异步操作就可以完成,但是在复杂的场景下很难对于异步流进行管理和维护,这时就需要借助redux中间件了,类似redux-thunkredux-saga,而这也是使用hooks无法实现的,无法处理副作用,拦截action去更好的reducer

总结

当然,并不是说采用react hooks所实现的状态管理方式没有好处,这样可以更加贴合react原生,采用react自身所提供的hook,并且可以减少项目中的redux各种实例、减少代码体积,对于小型项目或是不需要很多全局状态的项目,这种方式确实是不错的选择。但是redux仍然是大型项目中最可靠的保障存在。

以上就是useReducer createContext代替Redux原理示例解析的详细内容,更多关于useReducer createContext代替Redux的资料请关注我们其它相关文章!

(0)

相关推荐

  • React+TypeScript进行项目构建案例讲解

        react项目构建可以很简单,但是如果是结合typescript,其实也不是很麻烦,官网也有很明确的说明.有两种办法:     1.直接构建带有typescript的react项目,我们需要增加额外的参数,模版不能使用默认的cra-template.而是使用cra-template-typescript. npx create-react-app tsreactdemo --template typescript           创建完成的成功提示与原来没有太大的区别,直接进入项目路

  • 使用 TypeScript 开发 React 函数式组件

    目录 前言 如何使用 TypeScript 定义函数式组件 1. 使用 React.FC 2. 使用 JSX.Element 3. 直接定义完整类型 4. 使用 React.PropsWithChildren 使用过程需要注意的点 1. 函数式组件返回值不能是布尔值 2. 无法为组件使用 Array.fill() 填充 3. 支持使用泛型来创建组件 前言 在我们使用 React 开发项目时,使用最多的应该都是组件,组件又分为函数组件和类组件,我们可以这么定义: 定义函数组件: function

  • React TypeScript 应用中便捷使用Redux Toolkit方法详解

    目录 前言 背景 Redux-Toolkit 常规使用 优化方案 优化 useDispatch 和 useSelector 优化修改 redux 状态的步骤 总结 前言 本文介绍的主要内容是 Redux-Toolkit 在 React + TypeScript 大型应用中的实践,主要解决的问题是使用 createSlice 的前提下消费 redux 状态仍旧有点繁琐的问题. 阅读本文需要的前置知识:了解 React .Redux-Toolkit .TypeScript 的使用. 关于 Redux

  • 简易的redux createStore手写实现示例

    目录 1.首先创建一个store 2.其次创建一个my-redux 书写getState()方法 书写dispatch方法 书写subscribe方法 特别注意: 3.创建一个Test组件进行检测. 1. 将Test组件记得引入App根组件 2. 将store引入Test组件 3. 创建一个类组件,并且使用store.getState()获得状态值 4. 书写对应的点击按钮 1.首先创建一个store 沙箱链接 根目录创建一个store文件夹,下面创建一个index.js import { cr

  • redux功能强大的Middleware中间件使用学习

    目录 引言 redux中的Middleware 记录日志 手动记录 redux-saga Generator函数 实际使用场景 引言 上一节我们学习了redux在实际项目的应用细节,这一节我们来学习redux中一个很重要的概念:中间件.我们会简单实现一个记录的中间件, 然后学习redux-saga这个异步请求中间件. redux中的Middleware redux中的中间件提供的是位于 action 被发起之后,到达 reducer 之前的扩展点. 你可以利用 Redux middleware

  • 深入学习TypeScript 、React、 Redux和Ant-Design的最佳实践

    前言 阿特伍德定律,指的是any application that can be written in JavaScript, will eventually be written in JavaScript,意即"任何可以用JavaScript来写的应用,最终都将用JavaScript来写" 在使用新技术的时候,切忌要一步一步的来,如果当你尝试把两门不熟悉的新技术一起结合使用,你很大概率会被按在地上摩擦,会yarn/npm和React脚手架等技术是前提,后面我会继续写PWA深入和No

  • useReducer createContext代替Redux原理示例解析

    目录 前言 采用react-redux实现 采用react hooks模拟redux实现 异步action 总结 前言 最近看到很多采用useReducer + createContext 实现一个简易的redux的方案,今天亲自试了一下,发现还是会有一些区别的. 采用react-redux实现 这里使用react-redux 实现一个简单的状态管理例子. App.jsx根组件 import React from 'react'; import { Button } from './Button

  • Kotlin协程之Flow基础原理示例解析

    目录 引言 一.Flow的创建 二.Flow的消费 1.SafeFlow类 2.AbstractFlow类 3. SafeCollector类 4.消费过程中的挂起 引言 本文分析示例代码如下: launch(Dispatchers.Main) { flow { emit(1) emit(2) }.collect { delay(1000) withContext(Dispatchers.IO) { Log.d("liduo", "$it") } Log.d(&qu

  • go语言csrf库使用实现原理示例解析

    目录 引言 csrf小档案 一.CSRF及其实现原理 CSRF攻击示例 二.如何预防 三.CSRF包的使用及实现原理 csrf包的安装 基本使用 使用net/http包启动的服务 echo框架下使用csrf包 gin框架下使用csrf包 beego框架下使用csrf包 实现原理 csrf结构体 csrf包的工作流程 为什么GET.HEAD.OPTIONS.TRACE的请求方法不需要token验证 总结 引言 今天给大家推荐的是web应用安全防护方面的一个包:csrf.该包为Go web应用中常见

  • react fiber执行原理示例解析

    目录 为什么要使用fiber,要解决什么问题? fiber是什么? 数据结构 执行单元 浏览器工作: Fiber执行原理 workInProgress tree: currentFiber tree: Effects list: render阶段: 遍历节点过程: 收集effect list: commit阶段: 为什么commit必须是同步的操作的? 为什么要使用fiber,要解决什么问题? 在 react16 引入 Fiber 架构之前,react 会采用递归方法对比两颗虚拟DOM树,找出需

  • flutter Bloc 实现原理示例解析

    目录 序言 1. 事件流 > 状态流 (中转) 2. 使用 BlocBuilder 实时监听状态变更, 如何实现的呢? 总结 扩展 序言 在flutter开发中,我们使用 bloc 框架,基于状态变更进行响应式开发.本篇文章,小轰将 bloc 核心业务块进行拆解简化,聊一聊它的实现思想,bloc 核心能力分为如下两点: 添加事件 event,将 '事件流' 转换为 '状态流' state 监听 bloc 流,每次 state 状态变更,通知 widget 更新 下面,用自定义Bloc的方式,来给

  • java LockSupport实现原理示例解析

    目录 引言 LockSupport常见函数 LockSupport.park LockSupport.unpark 引言 前文中了解到AQS借助LockSupport.park和LockSupport.unpark完成线程的阻塞和唤醒,那么LockSupport内部又是怎么实现的?这是一个什么类? LockSupport是用于使用锁阻塞线程的基础实现,是其他同步类的基础,这个类为每个使用它的线程关联一个许可证(有点类似于Semaphore),如果许可证可用,线程调用park方法时会立即返回,线程

  • go sync Once实现原理示例解析

    目录 正文 Once 的实现 使用示例 Once 的一些工作机制 Once 详解 hotpath atomic.LoadUint32 atomic.StoreUint32 Mutex 总结 正文 在很多情况下,我们可能需要控制某一段代码只执行一次,比如做某些初始化操作,如初始化数据库连接等. 对于这种场景,go 为我们提供了 sync.Once 对象,它保证了某个动作只被执行一次. 当然我们也是可以自己通过 Mutex 实现 sync.Once 的功能,但是相比来说繁琐了那么一点, 因为我们不仅

  • 网页资源阻塞浏览器加载的原理示例解析

    目录 正文 测试前环境准备 图片会造成阻塞吗? CSS 加载阻塞 CSS 会阻塞后面 JS 的执行吗? JS 加载阻塞 defer 和 async 动态脚本会造成阻塞吗? DOMContentLoaded 和 onload DOMContentLoaded 遇到脚本 DOMContentLoaded 遇到样式 正文 一个页面允许加载的外部资源有很多,常见的有脚本.样式.字体.图片和视频等,对于这些外部资源究竟是如何影响整个页面的加载和渲染的呢?今天来一探究竟. 如何用 Chrome 定制网络加载

  • OPENMP SECTIONS CONSTRUCT原理示例解析

    目录 前言 编译器角度分析 动态库函数分析 总结 前言 在本篇文章当中主要给大家介绍 OpenMP 当中主要给大家介绍 OpenMP 当中 sections construct 的实现原理以及他调用的动态库函数分析.如果已经了解过了前面的关于 for 的调度方式的分析,本篇文章就非常简单了. 编译器角度分析 在这一小节当中我们将从编译器角度去分析编译器会怎么处理 sections construct ,我们以下面的 sections construct 为例子,看看编译器是如何处理 sectio

  • open 打开浏览器的过程原理示例解析

    目录 前言 使用 open open 的实现原理 总结 前言 启动项目时,在本地服务器启动后会自动帮我们打开浏览器,程序是如何做到呢?又是哪些代码在起作用呢?希望通过本章节的学习,达成如下目标: 学习程序自动打开浏览的原理 学会使用 Node.js 强大的 child_process 模块 源码地址:sindresorhus/open npm: open - npm (npmjs.com) 使用 配置 webpack 的 devServer 选项: module.exports = { //..

随机推荐