使用Zustand时子组件状态无法更新的问题求助
问题:Zustand子组件状态无法更新,点击Add后count始终为1
我是Zustand新手,用它做状态管理。应用包含一个父组件和两个被其包裹的子组件,尝试在子组件中创建状态,但点击Add按钮后子组件的count始终停留在1,状态无法正常更新,请问原因是什么?
相关代码
App.js
import "./styles.css"; import useCounterStore from "./hooks/useCounterStore"; import Child from "./Child"; export default function App() { const { count, add } = useCounterStore(); return ( <div> Parent <div className="childContainer"> <Child name="child1"></Child> <Child name="child2"></Child> </div> <p>{count}</p> <button onClick={add}>Add</button> </div> ); }
Child.js
import create from "zustand"; export default function Child(props) { const { name } = props; const { count, add } = create((set) => ({ count: 1, add: () => set((state) => ({ count: state.count + 1 })) }))(); return ( <div className="child"> <p>{name}</p> <p>{count}</p> <button onClick={add}>Add</button> </div> ); }
useCounterStore.js
import create from "zustand"; const useCounterStore = create((set) => ({ count: 1, add: () => set((state) => ({ count: state.count + 1 })) })); export default useCounterStore;
原因分析
核心问题是每次Child组件渲染时,都会重新调用create(...)()生成一个全新的Zustand Store实例:
- 点击Add按钮时,确实更新了当前Store的count值,但组件会因为状态变化触发重新渲染;
- 重新渲染时,Child组件再次执行
create方法,生成一个初始count为1的新Store,覆盖了之前的实例,所以界面始终显示1; - Zustand的
create方法设计为在组件外部定义,才能保证组件生命周期内始终使用同一个Store实例。
解决方案
方案1:将子组件的Store抽为独立hook(共享状态)
如果两个子组件需要共享同一个计数器状态,把Child的Store抽成独立文件:
创建useChildCounterStore.js
import create from "zustand"; const useChildCounterStore = create((set) => ({ count: 1, add: () => set((state) => ({ count: state.count + 1 })) })); export default useChildCounterStore;
修改Child.js
import useChildCounterStore from "./useChildCounterStore"; export default function Child(props) { const { name } = props; const { count, add } = useChildCounterStore(); return ( <div className="child"> <p>{name}</p> <p>{count}</p> <button onClick={add}>Add</button> </div> ); }
方案2:为每个子组件创建独立Store实例
如果需要两个子组件各自拥有独立的计数器状态,用useMemo缓存Store实例,避免每次渲染重新创建:
创建createChildCounterStore.js
import create from "zustand"; // 工厂函数,用于生成独立的Store实例 const createChildCounterStore = () => create((set) => ({ count: 1, add: () => set((state) => ({ count: state.count + 1 })) })); export default createChildCounterStore;
修改Child.js
import { useMemo } from "react"; import createChildCounterStore from "./createChildCounterStore"; export default function Child(props) { const { name } = props; // 用useMemo确保组件生命周期内只创建一次Store实例 const useCounterStore = useMemo(() => createChildCounterStore(), []); const { count, add } = useCounterStore(); return ( <div className="child"> <p>{name}</p> <p>{count}</p> <button onClick={add}>Add</button> </div> ); }
内容的提问来源于stack exchange,提问作者Ae Leung
相关产品推荐
相关产品推荐

