如何在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
相关产品推荐
相关产品推荐

