当前位置: 首页 > news >正文

react使用ctx和reducer代替redux

入门版本

创建一个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.jsqmd.com/news/2904/

相关文章:

  • KM 乱记
  • 深入解析:B树与B+树的原理区别应用
  • linux中的服务监控,停用自动重启
  • RHEL7/CentOS7 install NVIDIA drivers and CUDA
  • 浅谈 Burnside 和 Polya 的证明
  • 算法学习笔记:支配对
  • 在Windows10 Edge浏览器里安装DeepSider大模型插件来免费运用gpt-4o、NanoBanana等AI大模型
  • 西电PCB设计指南第5章学习笔记
  • ImageMagick - 关于图片压缩,通过dk整理的一些可用指令 - window64
  • 【杂记】原 hack
  • 全新升级!EasyDSS会议管理3大核心功能,让远程协作更高效
  • 黄金、原油期货数据API对接文档
  • 我的笔记方案
  • 聊聊前序、中序、后序表达式
  • flink书籍 - --
  • Asp.Net Core 鉴权授权
  • 遇到一款无人机,上面有安全模式和强力模式,十分迷惑二者区别,问了技术说是和碰撞指数有关,涨知识
  • 124
  • 我的笔记记录方案
  • AT_arc156_d [ARC156D] Xor Sum 5
  • iOS Provisioning Profile 证书 描述文件
  • 告别多工具切换的低效时代:PandaWiki如何无缝集成企业现有工作流?
  • 计算快速付氏变换FFT前需要加窗函数
  • 直播预告| PostgreSQL 与 IvorySQL 在云原生时代的演进与实践
  • 压垮项目经理的“三座大山”:时间、成本、质量的生存法则与破局工具
  • 最新微信机器人开发教程
  • 金蝶AAS (Apusic Application Server) v10 部署SuperMap iServer 2025 详细教程
  • AI智能会话原型解析:知识问答与知识库管理的设计思路(附模版)
  • Linux - Nginx 文件访问403 forbidden = 授权 chmod -R 777 文件名称
  • 阻抗匹配技术:信号完整性与功率传输的基石​​