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

如何在React Hooks之间实现共享数据存储?

React自定义Hook间的数据共享方案

针对你提到的多个列表管理Hook(usePageSize/usePageNumber/useApi等)需要共享数据的场景,以下是几种实用的实现方案:

1. 封装顶层容器Hook(最直接的方案)

把所有关联的状态、逻辑集中到一个顶层Hook里,各个子Hook本质是对顶层Hook的功能切片,通过顶层Hook内部的状态实现自动共享。

示例代码

// 顶层列表管理Hook,统一维护所有共享状态和逻辑
function useListManager() {
  // 初始化所有共享状态
  const [pageSize, setPageSize] = useState(10);
  const [pageNumber, setPageNumber] = useState(1);
  const [filters, setFilters] = useState({});
  const [sortConfig, setSortConfig] = useState({ key: '', direction: 'asc' });
  const [data, setData] = useState([]);
  const [loading, setLoading] = useState(false);

  // 实现usePageNumber依赖data的逻辑:数据为空时重置页码为1
  useEffect(() => {
    if (data.length === 0) {
      setPageNumber(1);
    }
  }, [data]);

  // 实现useApi的请求逻辑,自动依赖当前分页、筛选、排序参数
  const fetchData = useCallback(async () => {
    setLoading(true);
    try {
      // 替换为你的实际API请求
      const response = await fetch(`/api/list?pageSize=${pageSize}&pageNumber=${pageNumber}`);
      const resData = await response.json();
      setData(resData);
    } catch (err) {
      console.error('请求失败:', err);
    } finally {
      setLoading(false);
    }
  }, [pageSize, pageNumber, filters, sortConfig]);

  // 暴露各个子Hook需要的状态和操作方法
  return {
    // 分页相关
    pageSize,
    setPageSize,
    pageNumber,
    setPageNumber,
    // 筛选排序相关
    filters,
    setFilters,
    sortConfig,
    setSortConfig,
    // 数据与请求相关
    data,
    loading,
    fetchData
  };
}

// 封装子Hook,方便单独调用
function usePageSize() {
  const { pageSize, setPageSize } = useListManager();
  return [pageSize, setPageSize];
}

function usePageNumber() {
  const { pageNumber, setPageNumber } = useListManager();
  return [pageNumber, setPageNumber];
}

function useApi() {
  const { data, loading, fetchData } = useListManager();
  return { data, loading, fetchData };
}

优势:逻辑集中,状态流转清晰,不需要额外的Context或Store,适合中小型列表场景。


2. 用useReducer创建共享状态容器

如果状态更新逻辑复杂(比如多条件触发页码重置、多维度筛选排序),可以用useReducer统一管理状态变更,各个子Hook通过调用共享的状态Hook获取数据。

示例代码

// 定义状态更新的reducer
function listReducer(state, action) {
  switch (action.type) {
    case 'SET_PAGE_SIZE':
      return { ...state, pageSize: action.payload };
    case 'SET_PAGE_NUMBER':
      return { ...state, pageNumber: action.payload };
    case 'SET_FILTERS':
      return { ...state, filters: action.payload };
    case 'SET_SORT_CONFIG':
      return { ...state, sortConfig: action.payload };
    case 'SET_DATA':
      // 数据为空时自动重置页码
      return action.payload.length === 0 
        ? { ...state, data: action.payload, pageNumber: 1 }
        : { ...state, data: action.payload };
    case 'SET_LOADING':
      return { ...state, loading: action.payload };
    default:
      return state;
  }
}

// 创建共享状态Hook
function useListState() {
  const initialState = {
    pageSize: 10,
    pageNumber: 1,
    filters: {},
    sortConfig: { key: '', direction: 'asc' },
    data: [],
    loading: false
  };
  const [state, dispatch] = useReducer(listReducer, initialState);
  return { state, dispatch };
}

// 子Hook基于共享状态实现功能
function usePageNumber() {
  const { state, dispatch } = useListState();
  const setPageNumber = (num) => dispatch({ type: 'SET_PAGE_NUMBER', payload: num });
  return [state.pageNumber, setPageNumber];
}

function useApi() {
  const { state, dispatch } = useListState();
  
  const fetchData = useCallback(async () => {
    dispatch({ type: 'SET_LOADING', payload: true });
    try {
      const response = await fetch(`/api/list?pageSize=${state.pageSize}&pageNumber=${state.pageNumber}`);
      const resData = await response.json();
      dispatch({ type: 'SET_DATA', payload: resData });
    } catch (err) {
      console.error('请求失败:', err);
    } finally {
      dispatch({ type: 'SET_LOADING', payload: false });
    }
  }, [state.pageSize, state.pageNumber, state.filters, state.sortConfig, dispatch]);
  
  return { data: state.data, loading: state.loading, fetchData };
}

优势:状态变更逻辑可预测,适合复杂状态流转的场景,方便后续扩展。


3. 结合Context实现跨组件+跨Hook共享

如果你的列表逻辑需要在多个组件中复用,且Hook需要跨组件共享状态,就把顶层Hook的状态放到Context中,子Hook通过useContext获取共享数据。

示例代码

// 创建Context
const ListContext = React.createContext();

// 实现Context Provider组件
function ListProvider({ children }) {
  const listState = useListManager(); // 复用第一个方案的顶层Hook
  return (
    <ListContext.Provider value={listState}>
      {children}
    </ListContext.Provider>
  );
}

// 子Hook通过useContext获取共享状态
function usePageSize() {
  const context = useContext(ListContext);
  if (!context) {
    throw new Error('usePageSize必须在ListProvider内部使用');
  }
  const { pageSize, setPageSize } = context;
  return [pageSize, setPageSize];
}

优势:同时支持跨Hook和跨组件的状态共享,适合大型应用中多组件复用列表逻辑的场景。


内容的提问来源于stack exchange,提问作者Json Dimas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 18:41:26