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

如何在React函数组件外访问Zustand Store?解决Hook调用报错

问题原因

你触发了React Hook的规则限制:React Hook必须在React函数组件或自定义React Hook的顶层调用,不能直接在普通工具文件的顶层、对象或普通函数里调用useStore(它本质是一个React Hook),所以ESLint报错了。

解决方法

以下三种方案可实现需求,根据你的使用场景选择:


方案一:将工具函数封装为自定义Hook

把工具函数改成自定义Hook(命名以use开头),这样就能合法调用useStore,且直接关联store状态,不用手动传参。

修改util.ts:

import useStore from "@/store/useStore";

// 自定义Hook,符合React Hook规则
const useUtilityFunctions = () => {
  const { roomState, setRoomState } = useStore();

  const sha512 = (str: string) => {
    return crypto.subtle.digest("SHA-512", new TextEncoder().encode(str)).then(buf => {
      return Array.prototype.map.call(new Uint8Array(buf), x => (('00' + x.toString(16)).slice(-2))).join('');
    });
  };

  const addRoom = (min_inv: number) => {
    if (roomState.length < min_inv) {
      setRoomState([
        ...roomState,
        {
          room_no: roomState.length + 1,
          adult: 0,
          child: 0,
          infant: 0,
        },
      ]);
    }
  };

  return { sha512, addRoom };
};

export default useUtilityFunctions;

组件内使用:

import useUtilityFunctions from '@/utils/util';

const MyComponent = () => {
  const { sha512, addRoom } = useUtilityFunctions();

  const handleAddRoom = () => addRoom(3);

  return <button onClick={handleAddRoom}>添加房间</button>;
};

方案二:直接访问Zustand Store实例

Zustand支持直接访问store原始实例,无需通过Hook,适合在非组件环境(如工具函数、异步逻辑)中调用。

第一步:修改store文件(store/useStore.ts)

导出store实例:

import { create } from 'zustand';

// 创建store实例
const store = create((set) => ({
  roomState: [],
  setRoomState: (newState) => set({ roomState: newState }),
  // 其他状态/方法...
}));

// 导出供组件使用的Hook
export default store;
// 导出供工具函数使用的实例
export const storeInstance = store;

第二步:修改util.ts

直接通过实例获取和修改状态:

import { storeInstance } from "@/store/useStore";

const utililtyFunctions = {
  sha512: (str: string) => {
    return crypto.subtle.digest("SHA-512", new TextEncoder().encode(str)).then(buf => {
      return Array.prototype.map.call(new Uint8Array(buf), x => (('00' + x.toString(16)).slice(-2))).join('');
    });
  },

  addRoom: (min_inv: number) => {
    const roomState = storeInstance.getState().roomState;
    if (roomState.length < min_inv) {
      storeInstance.setState({
        roomState: [
          ...roomState,
          {
            room_no: roomState.length + 1,
            adult: 0,
            child: 0,
            infant: 0,
          },
        ]
      });
    }
  },
};

export default utililtyFunctions;

调用方式不变,直接导入工具函数即可使用。


方案三:将状态和方法作为参数传入

让工具函数完全与store解耦,调用时手动传入roomState和setRoomState,适合需要适配不同状态来源的场景。

修改util.ts:

const utililtyFunctions = {
  sha512: (str: string) => {
    return crypto.subtle.digest("SHA-512", new TextEncoder().encode(str)).then(buf => {
      return Array.prototype.map.call(new Uint8Array(buf), x => (('00' + x.toString(16)).slice(-2))).join('');
    });
  },

  addRoom: (
    roomState: { room_no: number; adult: number; child: number; infant: number }[],
    setRoomState: (newState: typeof roomState) => void,
    min_inv: number
  ) => {
    if (roomState.length < min_inv) {
      setRoomState([
        ...roomState,
        {
          room_no: roomState.length + 1,
          adult: 0,
          child: 0,
          infant: 0,
        },
      ]);
    }
  },
};

export default utililtyFunctions;

组件内使用:

import useStore from '@/store/useStore';
import utililtyFunctions from '@/utils/util';

const MyComponent = () => {
  const { roomState, setRoomState } = useStore();

  const handleAddRoom = () => {
    utililtyFunctions.addRoom(roomState, setRoomState, 3);
  };

  return <button onClick={handleAddRoom}>添加房间</button>;
};

内容的提问来源于stack exchange,提问作者Ashutosh Dash

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 07:37:05