React Context 与 Zustand Store 集成方案
注:本文结合本人真实项目实践经验,经过 AI 润色。
引言
在现代 React 应用开发中,状态管理一直是开发者面临的核心挑战之一。虽然 Redux 曾是主流解决方案,但其繁琐的样板代码让许多开发者望而却步。Zustand 作为一个轻量级的状态管理库,提供了更简洁的 API 和更好的 TypeScript 支持,同时还能与 React Context 无缝集成。
核心概念解析
Zustand 基础
Zustand 的核心是 createStore 函数,它创建一个状态存储 (store)。与 Redux 不同,Zustand 的 store 不需要额外的 reducer 或 action 定义。
import { createStore } from 'zustand';
const useBearStore = createStore((set) => ({
bears: 0,
increasePopulation: () => set((s) => ({ bears: s.bears + 1 })),
}))
React Context 集成
在大型应用中,我们经常需要将 Zustand store 与 React Context 结合使用,以便在组件树中共享状态。下面的代码展示了一个典型的集成模式:
- 创建 Context
- 定义 store 类型和创建函数
- 创建 Provider 组件
- 创建自定义 Hook 来访问 store
代码
类型定义与 Store 创建
interface PageProps {
bears: number;
}
interface PageState extends PageProps {
addBear: () => void;
}
function createPageStore(initProps?: Partial<PageState>) {
const DEFAULT_PROPS: PageProps = {
bears: 0,
};
return createStore<PageState>()((set) => ({
...DEFAULT_PROPS,
...initProps,
addBear: () => {
set((s) => ({ bears: 1 }));
},
}));
}
type PageStore = ReturnType<typeof createPageStore>;
这里定义了组件的 props 接口 (PageProps)、扩展后的状态接口 (PageState),以及 store 类型 (PageStore)。这种类型定义方式确保了完整的 TypeScript 支持。
Provider 组件实现
export function PageProvider({ children, ...props }: PageProviderProps) {
const storeRef = useRef<PageStore>();
if (!storeRef.current) {
storeRef.current = createPageStore(props);
}
return <PageContext.Provider value={storeRef.current}>{children}</PageContext.Provider>;
}
Provider 组件使用 useRef 来保持 store 的稳定性,避免不必要的重新创建。这是性能优化的关键点。
自定义 Hook 访问
export function usePageContext<T>(selector: (state: PageState) => T): T {
const store = useContext(PageContext);
if (!store) throw new Error('Missing PageContext.Provider in the tree');
return useStore(store, selector);
}
这个自定义 Hook 封装了 Context 访问和 Zustand 的 useStore Hook,提供了类型安全的 selector 功能。
实际应用示例
初始化状态
export default function Page() {
return (
<PageProvider bears={2}>
<BearCounter />
<Controls />
</PageProvider>
);
}
组件中使用状态
function BearCounter() {
const bears = usePageContext((s) => s.bears);
return <div>{bears} bears around here</div>;
}
function Controls() {
const addBear = usePageContext((s) => s.addBear);
return <button onClick={addBear}>Add bear</button>;
}
性能优化技巧
- 细粒度订阅:Zustand 会自动进行浅比较,只在你选择的 state 部分发生变化时触发重新渲染
- 稳定引用:确保 store 创建只发生一次,使用
useRef来保持引用 - 选择器优化:尽量使用简单的选择器函数,避免在渲染时进行复杂计算
总结
- 对于小型应用,直接使用单个 Zustand 即可
- 对于多模块的中大型应用,合理拆分 store,避免单一 store 过于庞大。比如,你只是想为一个营销活动页面设计一个 store,可以采用本文的模式
- 始终为你的状态定义清晰的类型
通过这种模式,你可以在享受 Zustand 简洁 API 的同时,获得 React Context 提供的组件树隔离能力,为你的应用构建灵活且高效的状态管理系统。
React Context 与 Zustand Store 集成方案的更多相关文章
- JYadmin-react-antd react+antd封装的优秀后台模板集成方案("^1.0.0")
版本:[ "JYadmin-react-antd": "^1.0.0"] 版权所有:微信公众号[微新悦] 原文链接:https://www.weixinyue. ...
- Spring+Struts集成(方案一)
SSH框架是现在非常流行的框架之一,本文接下来主要来对Spring和Struts的集成进行展示. 集成原理:在Action中取得BeanFactory,通过BeanFactory取得业务逻辑对象. 集 ...
- (转)Spring4.2.5+Hibernate4.3.11+Struts1.3.8集成方案二
http://blog.csdn.net/yerenyuan_pku/article/details/52894958 前面我们已经集成了Spring4.2.5+Hibernate4.3.11+Str ...
- (转)Spring4.2.5+Hibernate4.3.11+Struts1.3.8集成方案一
http://blog.csdn.net/yerenyuan_pku/article/details/52888808 前面我们已经集成了Spring4.2.5+Hibernate4.3.11这两个框 ...
- 探索 Redux4.0 版本迭代 论基础谈展望(对比 React context)
Redux 在几天前(2018.04.18)发布了新版本,6 commits 被合入 master.从诞生起,到如今 4.0 版本,Redux 保持了使用层面的平滑过渡.同时前不久, React 也从 ...
- SSO集成方案[随笔]
看这个方案之前,先说明下为什么要加入SSO,以防对大家产生不好的影响.我们产品使用传统winform+db服务+Db存储方式开发,一群老菜帮子开发,以传统的datatble做数据传递,很多年了未有变化 ...
- Jmeter+Ant+Jenkins持续集成方案改进
关于Jmeter+Ant+Jenkins如何搭建持续集成环境,网上资料一大把,就不多说了,本文主要谈一下期间的问题及扩展该持续集成方案. 其实核心的流程不复杂,Jenkins管理构建项目,Ant配置脚 ...
- FineReport和泛微OA(Ecology)的单点登录集成方案
最近出现了很多关于帆软报表和泛微OA的集成问题,均出现在“单点登录”上.直接也有相关的文章介绍一些FineReport和泛微集成的背景.价值等,以及FineReport和OA的深度集成的方案,但是并没 ...
- React context基本用法
React的context就是一个全局变量,可以从根组件跨级别在React的组件中传递.React context的API有两个版本,React16.x之前的是老版本的context,之后的是新版本的 ...
- [React] Prevent Unnecessary Rerenders of Compound Components using React Context
Due to the way that React Context Providers work, our current implementation re-renders all our comp ...
随机推荐
- Java 记录操作日志|对象修改细节
背景描述 由于业务涉及收入敏感信息,需记录数据变更前的内容和变更后的内容,但是不能为完成任务而硬编码,要适用于不同bean.针对这种情况,本文使用泛型.反射和基于AOP的自定义注解技术来完成,对对 ...
- win10系统 wsappx消耗内存导致死机
问题描述:win10系统开机后,wsappx内存占用率一路飙升,直至电脑蓝屏,手动kill后,过一会死灰复燃. 问题解决:win+R输入 regedit 跳转注册表编辑器,找到 HKEY_LOCAL_ ...
- MyBatis常见面试题:说说MyBatis的工作原理
本文转自参考文献3. SSM风靡当前的Java世界,面试官不经意间就会甩出一道必杀题:请你说一下MyBatis的工作原理.虽然大家每天都在使用MyBatis做增删改查的工作,但是面对这个问题往 ...
- FastAPI安全门神:OAuth2PasswordBearer的奇妙冒险
title: FastAPI安全门神:OAuth2PasswordBearer的奇妙冒险 date: 2025/05/30 18:34:14 updated: 2025/05/30 18:34:14 ...
- MybatisPlus查询一对多list结果collection实例
前言 查询用户信息,结果放到一个实体类里 这个实体类里有两个List<对象>字段,分别是这个用户的角色列表.岗位列表 以下仅供参考 实体类 package cn.daenx.myadmin ...
- 终极指南:Scrum中如何设置需求优先级
需求众多不知道如何下手?总想先做简单的需求,复杂需求却一拖再拖?那么,我们是时候开始考虑如何设置需求优先级了. 本期终极指南将展示如何为需求设置有效优先级,如何有效管理工作量,让效率指数倍增长,搭配 ...
- 如何自建PT刷流盒子
如何自建PT刷流盒子 选择机器 为了刷流我们最好选择大带宽.大容量的服务器,在这里我们简称大盘鸡 在这里为了方便演示我就拿Digital Ocean的一台服务器进行搭建,如果你要正式刷流了还是买个硬盘 ...
- WinForms中实现Adobe PDF Reader实现旋转PDF功能
实现效果: 问题点:Adobe PDF Reader中并没有可以直接旋转的方法 LoadFile 加载文件,文件URL地址 GotoFirstPage 到第一页 GotoLastPage 到最后一页 ...
- 使用ajax来进行登录验证
servlet: 1 @WebServlet("/login.do") 2 public class AjaxLoginServlet extends HttpServlet { ...
- 关于PHP 函数性能优化的技巧
本文由 ChatMoney团队出品 本文将详细介绍 PHP 函数性能优化的技巧.通过分析 PHP 函数的执行过程和性能瓶颈,提供一系列实用的优化方法,并结合代码示例,帮助读者提升 PHP 代码的执行效 ...