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

如何将组件状态导出为自定义Hook并跨组件无Props使用

问题解决:自定义Hook共享组件状态(无需Props/Redux)

问题背景

需求是通过自定义Hook在OtherComp中访问MyComp内部的请求数据,无需Props传递,同时避免父组件状态导致的全局重渲染。当前MyComp能正常渲染请求数据,但OtherComp调用useMyHook时返回空数组,因为两次Hook调用的状态是独立实例。

问题根源

原useMyHook中使用的useState是组件级独立状态,每次调用Hook都会创建全新的状态实例,所以MyComp和OtherComp的data完全隔离,无法共享。

解决方案:全局状态+订阅模式

通过实现一个全局状态容器,配合订阅机制,让所有调用useMyHook的组件共享同一份状态,同时只在状态变化时更新订阅的组件,避免全局重渲染。

1. 改造自定义Hook useMyHook.ts

import { useState, useEffect } from 'react';

// 全局单例状态存储真实数据
let globalData: any[] = [];
// 存储订阅组件的状态更新函数
const subscribers: Set<(data: any[]) => void> = new Set();

// 更新全局状态并通知所有订阅者
const setGlobalData = (newData: any[]) => {
  globalData = newData;
  // 传递副本避免引用类型导致的意外更新
  subscribers.forEach(update => update([...globalData]));
};

export const useMyHook = () => {
  // 组件本地状态,用于触发组件重渲染
  const [localData, setLocalData] = useState([...globalData]);

  useEffect(() => {
    // 订阅全局状态变化
    const updateLocalState = (newData: any[]) => setLocalData(newData);
    subscribers.add(updateLocalState);

    // 组件卸载时取消订阅,防止内存泄漏
    return () => subscribers.delete(updateLocalState);
  }, []);

  const addItem = (item: unknown) => {
    setGlobalData([...globalData, item]);
  };

  return {
    data: localData,
    setData: setGlobalData,
    addItem,
  };
};

export default useMyHook;

2. 保持MyComp.tsx逻辑不变

import { useEffect } from 'react';
import useMyHook from './useMyHook';

const MyComp = () => {
  const { data, setData } = useMyHook();

  const req = async () => {
    // 模拟异步请求
    const { values } = await new Promise(resolve => {
      setTimeout(() => resolve({ values: [{ name: 'Example1' }, { name: 'Example2' }] }), 1000);
    });
    setData(values);
  };

  useEffect(() => { req() }, []);

  return (
    <div>
      {data.map((item, index) => <p key={index}>{item.name}</p>)}
    </div>
  );
};

export { useMyHook };
export default MyComp;

3. OtherComp使用方式保持不变

import MyComp, { useMyHook } from '../../../components/MyComp';

const OtherComp = () => {
  const { data } = useMyHook();

  return (
    <div>
      <button type="button" onClick={() => console.log(data)}>
        click test
      </button>
      <MyComp />
    </div>
  );
};

export default OtherComp;

效果说明

  • MyComp请求完成后更新全局状态,所有订阅了useMyHook的组件(包括OtherComp)会同步拿到最新数据
  • 只有订阅的组件会在状态变化时重渲染,避免全局不必要的更新
  • 无需Props传递,也不依赖Redux等外部状态管理库

内容的提问来源于stack exchange,提问作者Dhenyson Jhean

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 16:35:50