You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 11:45:32