如何在API Context中注入Service并实现二者通信?
让Service与Context实现通信的方案
核心思路是让Context Provider调用Service的API请求方法,将请求结果更新到Context的状态中,同时把状态和触发请求的方法暴露给子组件使用。具体步骤如下:
1. 简化Service的写法(可选但更实用)
你的当前Service是一个工厂函数,其实可以直接导出请求函数,减少不必要的函数调用:
// CategoryService.js export const fetchCategoryData = async () => { try { const response = await fetch("http://192.168.1.68:19000/animal/categories/main_groups/", { method: "GET", }); if (!response.ok) { throw new Error("Network response was not ok"); } return await response.json(); } catch (error) { console.error("There was a problem with the fetch operation:", error); throw error; } };
2. 在Context Provider中整合Service逻辑
修改Context Provider,导入Service的请求函数,封装加载数据的方法,同时管理加载状态、数据和错误信息:
// CategoryContext.js import { createContext, useState, useCallback } from "react"; import { fetchCategoryData } from './CategoryService'; const CategoryContext = createContext(); export const CategoryContextProvider = (props) => { const [categoryList, setCategoryList] = useState([]); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); // 新增错误状态,方便组件处理异常 // 用useCallback缓存方法,避免组件重复渲染 const loadCategoryData = useCallback(async () => { setLoading(true); setError(null); try { // 调用Service的请求函数获取数据 const data = await fetchCategoryData(); setCategoryList(data); } catch (err) { setError(err.message); } finally { // 请求结束无论成功失败都关闭加载状态 setLoading(false); } }, []); // 可选:如果需要组件挂载时自动加载数据,取消下面的注释 // useEffect(() => { // loadCategoryData(); // }, [loadCategoryData]); // 把状态和方法放入Context的value中 const value = { categoryList, loading, error, loadCategoryData, // 提供给子组件触发数据加载的方法 }; return <CategoryContext.Provider value={value}>{props.children}</CategoryContext.Provider>; }; export default CategoryContext;
3. 组件中使用Context消费数据和方法
在需要使用分类数据的组件中,通过useContext获取Context中的状态和方法:
// CategoryList.js import { useContext, useEffect } from 'react'; import CategoryContext from './CategoryContext'; const CategoryList = () => { const { categoryList, loading, error, loadCategoryData } = useContext(CategoryContext); // 组件挂载时触发数据加载,也可以通过按钮点击等事件触发 useEffect(() => { loadCategoryData(); }, [loadCategoryData]); if (loading) return <div>加载中...</div>; if (error) return <div>加载出错:{error}</div>; return ( <ul> {categoryList.map(category => ( <li key={category.id}>{category.name}</li> ))} </ul> ); }; export default CategoryList;
逻辑说明
- Service只负责处理网络请求的底层逻辑,不关心状态管理
- Context Provider负责管理数据状态、加载状态和错误状态,并封装调用Service的方法
- 子组件只需通过Context获取状态和触发方法,无需直接和Service交互,实现了逻辑解耦
内容的提问来源于stack exchange,提问作者mightycode Newton
相关产品推荐
相关产品推荐

