React中串联两个API请求的写法是否合理?求优化方案
React关联两个API请求的优化方案
你的代码存在一个潜在问题:第二个.then里访问data.compte.id时,setData是异步操作,此时data还没更新到最新值,可能导致第二个API请求拿不到正确的id,甚至报错。下面是几种更优的实现方式:
方式一:使用async/await(推荐)
async/await让异步代码逻辑更直观,同时直接用第一个请求的响应数据获取id,避开state异步更新的问题:
const [data, setData] = useState([]); const [data2, setData2] = useState([]); useEffect(() => { const fetchRelatedData = async () => { try { // 发起第一个API请求 const firstResponse = await axios.get(api, config); setData(firstResponse.data); // 从第一个请求的响应中获取id,发起第二个请求 const compteId = firstResponse.data.compte.id; const secondResponse = await axios.get(`http://localhost:8000/api/compte/${compteId}`, config); setData2(secondResponse.data); } catch (error) { console.error('请求失败:', error); } }; fetchRelatedData(); }, []);
方式二:规范链式调用
如果习惯用.then链式写法,要把第二个请求放在第一个请求的.then内部,直接使用响应数据而非state:
const [data, setData] = useState([]); const [data2, setData2] = useState([]); useEffect(() => { axios.get(api, config) .then(firstResponse => { setData(firstResponse.data); // 直接用响应里的id发起第二个请求,并返回Promise继续链式调用 return axios.get(`http://localhost:8000/api/compte/${firstResponse.data.compte.id}`, config); }) .then(secondResponse => { setData2(secondResponse.data); }) .catch(error => { console.error('请求失败:', error); }); }, []);
额外优化建议
- 添加请求取消逻辑:避免组件卸载后未完成的请求导致内存泄漏:
useEffect(() => { const cancelTokenSource = axios.CancelToken.source(); const fetchRelatedData = async () => { try { const firstResponse = await axios.get(api, { ...config, cancelToken: cancelTokenSource.token }); setData(firstResponse.data); const compteId = firstResponse.data.compte.id; const secondResponse = await axios.get(`http://localhost:8000/api/compte/${compteId}`, { ...config, cancelToken: cancelTokenSource.token }); setData2(secondResponse.data); } catch (error) { // 忽略取消请求的错误 if (!axios.isCancel(error)) { console.error('请求失败:', error); } } }; fetchRelatedData(); // 组件卸载时取消所有未完成的请求 return () => cancelTokenSource.cancel('组件已卸载,取消请求'); }, []); - 合并关联状态:如果两个请求的数据是强关联的,可以合并成一个state对象,简化状态管理:
const [combinedData, setCombinedData] = useState({ mainData: [], compteData: [] }); // 更新状态时: setCombinedData(prev => ({ ...prev, mainData: firstResponse.data })); setCombinedData(prev => ({ ...prev, compteData: secondResponse.data }));
内容的提问来源于stack exchange,提问作者Yasuraka
相关产品推荐
相关产品推荐

