react使用ctx和reducer代替redux

news/2025/9/24 16:06:49/文章来源:https://www.cnblogs.com/dingshaohua/p/19109397

入门版本

创建一个store,包含ctx、reduce、dispatch+action

import { createContext, useContext } from 'react';// 定义ctx
export const defaultValue = {count: 0,
};
export const AppCtx = createContext(null);export function useAppCtx() {const ctx = useContext(AppCtx);return ctx;
}// 定义reducer
export function appReducer(app, action) {switch (action.type) {case 'update': {return { ...app, ...action.payload };}case 'clear': {return {};}default: {throw Error('Unknown action: ' + action.type);}}
}// 定义dispatch和action(省的在组件手写dispatch)
export const appCtxDispatch = {update: (dispatch, payload) => {dispatch({type: 'update',payload,});},clear: (dispatch) => {dispatch({type: 'clear',})},
};

最后我们在组件中使用

import { memo, useReducer } from 'react';
import { AppCtx, appReducer, defaultValue, useAppCtx, appCtxDispatch } from '@/hooks/useAppCtx';// 子组件
const Demo = memo(() => {console.log('Demo render');const { app } = useAppCtx();return (<div>我是子组件<div>{JSON.stringify(app)}</div></div>);
});// 父组件
const App = () => {console.log('App render');const [app, dispatch] = useReducer(appReducer, defaultValue);const doInc = () => {appCtxDispatch.update(dispatch, {count: app.count + 1,});};return (<AppCtx value={app}><div>{app.count}</div><button onClick={doInc} className="bg-blue-400 p-1 rounded text-white">改变组件</button><hr className="mt-2" /><Demo /></AppCtx>);
};

优化版本

解决无辜组件的不必要的重新render问题

// app-store.ts
import { produce } from 'immer';
import { createContext, useContext } from 'react';// 定义ctx
export const defaultValue = {count: 0,
};
export const AppCtx = createContext(null);export function useAppCtx() {const ctx = useContext(AppCtx);return ctx;
}// 定义reducer
// 优化1: 使用immer,防止payload内容不变,而返回全新的对象导致 使用的地方被rerender
export function appReducer(app, action) {return produce(app, (draft) => {switch (action.type) {case 'update': {Object.assign(draft, action.payload); // 只真正改动的字段会触发草稿变更return; // 没改动时 Immer 自动返回旧引用}case 'clear': {return {};}default:throw new Error('Unknown action: ' + action.type);}});
}// 定义dispatch和action(省的在组件手写dispatch)
export const appCtxDispatch = {update: (dispatch, payload) => {dispatch({type: 'update',payload,});},clear: (dispatch) => {dispatch({type: 'clear',});},
};

组件中使用

import { memo, useMemo, useReducer } from 'react';
import { AppCtx, appReducer, defaultValue, useAppCtx, appCtxDispatch } from '@/hooks/useAppCtx';// 子组件
const Demo = memo(() => {console.log('Demo render');const { app } = useAppCtx();return (<div>我是子组件<div>{JSON.stringify(app)}</div></div>);
});// 父组件
const App = () => {console.log('App render');const [app, dispatch] = useReducer(appReducer, defaultValue);const doInc = () => {appCtxDispatch.update(dispatch, {count: app.count+1,});};// 优化2: 防止App本身render,导致ctx的值被迫改变const appCtxValue = useMemo(() => ({ app, dispatch }), [app]); return (<AppCtx value={appCtxValue}><div>{app.count}</div><button onClick={doInc} className="bg-blue-400 p-1 rounded text-white">改变组件</button><hr className="mt-2" /><Demo /></AppCtx>);
};

其它

ctx provider的使用最好精确到使用位置,不要什么都在顶部放,
以及 ctx state也别什么都放,
假设当到了根组件app上使用了且还随意放了很多状态:那只要ctx内容变了,所有子组件及其孙子子子子都会rerender,后期我们只能通过memo来包裹来避免!

react的原则是,跨组件都要用到的共性数据,方可提取ctx!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/915916.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

KM 乱记

狠狠学习了先来看一个问题:给定 \(w_{1\sim n, 1\sim n}\),现在要求满足 \(\forall i, j\in [1, n], a_i + b_j\ge w_{i, j}\) 且 \(\sum a_i + \sum b_j\) 最小的 \(a_{1\sim n}, b_{1\sim n}\)。如果会线性规划对偶…

深入解析:B树与B+树的原理区别应用

深入解析:B树与B+树的原理&区别&应用pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", &q…

linux中的服务监控,停用自动重启

#! /bin/shexport JAVA_HOME=/usr/lib/jvm/TencentKona-8.0.9-322/jre/bin/javaexport CLASSPATH=.:CLASSPATH:$JAVA_HOME/lib/export PATH=$PATH:$JAVA_HOME/bin# 进程名称proc_name=blog-1.0.0.jar#启动命令boot_cmd…

元氏县城有做网站广告的吗wordpress防爆破插件

想要在本地运行大型语言模型吗&#xff1f; Ollama框架提供了这样的机会。 这个框架是专为在Docker容器中部署LLM而设计的&#xff0c;简化了部署和管理流程。 安装Ollama后&#xff0c;你只需执行一条命令&#xff0c;即可在本地运行开源大型语言模型。 它将模型权重、配置…

RHEL7/CentOS7 install NVIDIA drivers and CUDA

# 1. 查看系统是否可以识别到 NVIDIA 显卡 lspci |grep -i nvidia # 2. 安装内核文件确保和内核版本一致 yum install kernel-devel kernel-headers yum install kernel-devel-$(uname -r) kernel-headers-$(uname -r)…

浅谈 Burnside 和 Polya 的证明

前言 请怀着批判性思维阅读,如果有任何问题欢迎前来踩爆我。 群 定义 如果一个集合 \(S\ne \varnothing\),且在 \(S\) 上的运算 \(\cdot\) 满足一下要求,得到我们称 \((S,\cdot)\) 为一个群。封闭性:\(\forall a,b…

算法学习笔记:支配对

引入 支配对通常用来解决一类点对贡献问题。具体来说,任意两个对象构成一个点对,我们做一定范围内的信息查询时,就相当于查询范围内的点对的信息并。但是这样点对的数量是 \(\mathcal{O}(n^2)\) 量级的,无法接受。…

在Windows10 Edge浏览器里安装DeepSider大模型插件来免费运用gpt-4o、NanoBanana等AI大模型

在Windows10 Edge浏览器里安装DeepSider大模型插件来免费运用gpt-4o、NanoBanana等AI大模型pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !import…

西电PCB设计指南第5章学习笔记

西电PCB设计指南第5章学习笔记 五、常见类型PCB设计敏感电路常见的敏感电路 音频电子系统前级、精密仪器、光电探测转换电路、传感器特点: 容易受干扰的电路受干扰的原因: 空间电场耦合、磁场耦合、电路板绝缘不良的…

网站建设及管理使用情况汇报去菲律宾做it网站开发

背景 如果想在运行过程中想基于nacos数据变更做一些业务&#xff0c;比如想在运行过程中变更日志的级别&#xff0c;那么我们可以扩展nacos的监听。 步骤 定义一个配置类&#xff0c;用NacosConfigListener标记需要触发的方法&#xff0c;并用dataId标记需要监听的文件。如下…

ImageMagick - 关于图片压缩,通过dk整理的一些可用指令 - window64

测试可以通过命令行批量处理指定类型图片,少量图片的话直接搜“图压”就行了,一般图片还是可以的 下载链接:https://imagemagick.org/script/download.php window系统往下滑找到这个下载 指令: 进入对应文件夹下压…

【杂记】原 hack

键盘声碎打工夜,洛谷光寒算法天。 一题路径成疑冢,千军码农陷迷烟。 小蝙振翅破虚妄,数据如雷震前贤。 莫笑代码无证处,敢教日月换新篇!(抚尺一拍)列位看官,今日且听我道一段「洛谷奇谭芙卡米破阵记」!有诗为…

全新升级!EasyDSS会议管理3大核心功能,让远程协作更高效

在数字化浪潮中,高效便捷的视频会议系统已成为企业刚需。随着远程办公和跨地域协作的普及,企业对视频会议平台的要求也越来越高。 新版EasyDSS作为强大的流媒体服务器解决方案,重磅升级会议管理功能,为企业带来全场…

黄金、原油期货数据API对接文档

本文档提供StockTV期货市场数据API的完整对接指南,包含全球主要期货交易所的实时行情、历史数据、合约信息等核心功能一、接口概览 1.1 支持期货交易所交易所代码 交易所名称 主要期货品种CME 芝加哥商品交易所 股指、…

电商门户网站建设方案餐饮品牌设计哪个公司最好

对于做实体生意的中小商户来说&#xff0c;仓库管理工作是重中之重的&#xff0c;仓库管理的好坏&#xff0c;直接影响着门店销售和财务状况。 但对于很多中小商户来说&#xff0c;没有足够的人力和精力去高效地做好仓库管理工作&#xff0c;而借助仓库管理软件或进销存软件来…

番禺网站建设怎样利用帝国软件如何做网站

Java后端开发技能&#xff1a; JVM&#xff1a;内存模型、类加载机制、双亲委派、垃圾回收算法、垃圾回收器、空间分配担保策略、可达性分析、强软弱虚引用、GC的过程、三色标记、跨代引用、内存泄漏与溢出多线程&#xff1a;集合、Synchronized、ThreadLocal、AQS、线程池JVM…

中国交建总承包公司官网wordpress 谷歌seo

WebAPI 和 MVC 的管道不同 1.Restful 架构风格和WebAPI 2.WebAPI 路由&特性路由 3.WebAPI 前后台调用 4.权限认证 5.跨域请求 6.WebAPI 依赖注入&面向切面 7.WebAPI 自动生成文档 .NETRemoting 速度很快 &#xff0c;平台要求&#xff0c; WebService 跨平台 &#x…

我的笔记方案

俗话说得好,好记性不如烂笔头,可见记好笔记是很重要的。那么我们该如何在电脑上记好笔记呢?下面我就来分享一下,我自己的记笔记方案。 记笔记工具 我使用 Typora 记笔记,这需要使用 MarkDown 语法。 关于 MarkDow…

聊聊前序、中序、后序表达式

在游戏开发中,我们经常需要在配置表中定义各种公式,比如 a * (b + c),用来计算技能伤害、属性加成等。如果直接让程序在运行时解析并执行这些公式,就需要处理运算符优先级和括号等复杂问题。 这时,后序表达式就派…

flink书籍 - --

本站整理下载:链接:https://pan.baidu.com/s/1P1bK-zdSuknnBuoAS6ZeXA 提取码:hfy9