useReducer+createContext真的可以代替Redux吗?
创始人
2024-04-03 07:58:17
0

在这里插入图片描22述

前言

最近看到很多采用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 (store}>
); }

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 (
() => dispatch({ type: 'UPDATENAME' })}>{useSelector((state) => state.name)}
); }

效果如图:

在这里插入图片描述

可以看到,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 ({ redux, dispatch }}>

A.jsx

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

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

在这里插入图片描述

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

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

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

 const renderButton = React.useMemo(() => {return 

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仍然是大型项目中最可靠的保障存在。

相关内容

热门资讯

监控摄像头接入GB28181平... 流程简介将监控摄像头的视频在网站和APP中直播,要解决的几个问题是:1&...
Windows10添加群晖磁盘... 在使用群晖NAS时,我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过...
protocol buffer... 目录 目录 什么是protocol buffer 1.protobuf 1.1安装  1.2使用...
在Word、WPS中插入AxM... 引言 我最近需要写一些文章,在排版时发现AxMath插入的公式竟然会导致行间距异常&#...
Fluent中创建监测点 1 概述某些仿真问题,需要创建监测点,用于获取空间定点的数据࿰...
educoder数据结构与算法...                                                   ...
MySQL下载和安装(Wind... 前言:刚换了一台电脑,里面所有东西都需要重新配置,习惯了所...
MFC文件操作  MFC提供了一个文件操作的基类CFile,这个类提供了一个没有缓存的二进制格式的磁盘...
有效的括号 一、题目 给定一个只包括 '(',')','{','}'...
【PdgCntEditor】解... 一、问题背景 大部分的图书对应的PDF,目录中的页码并非PDF中直接索引的页码...