如何仅在Axios响应与上一次响应内容不同时才更新state值
实现方案
- 首先修正原代码的死循环问题:原代码中useEffect的依赖项为
Data,每次调用setData更新Data都会重新触发useEffect执行、发起新请求,进而再次更新Data,陷入无限循环。如果是组件挂载后定期拉取接口数据,用定时器实现轮询即可;如果仅需组件挂载时拉取一次,直接把useEffect依赖项设为空数组。 - 新增新旧值校验逻辑:拿到接口返回的新值后,先和当前的
Data做对比,仅当值不一致时才更新state。如果接口返回的是引用类型(对象、数组),需要做深比较判断值是否相等,基础类型直接用===判断即可。
参考实现代码
import { useState, useEffect } from 'react'; import axios from 'axios'; import Home from './Home'; // 简易深比较函数,适用于普通对象/数组/基础类型,复杂场景可直接用lodash.isEqual function deepEqual(a, b) { if (a === b) return true; if (typeof a !== typeof b) return false; if (Array.isArray(a) && Array.isArray(b)) { if (a.length !== b.length) return false; return a.every((item, index) => deepEqual(item, b[index])); } if (typeof a === 'object' && a !== null && b !== null) { const keysA = Object.keys(a); const keysB = Object.keys(b); if (keysA.length !== keysB.length) return false; return keysA.every(key => deepEqual(a[key], b[key])); } return false; } function App() { const [Data, setData] = useState(0); useEffect(() => { // 定义请求函数 const fetchData = async () => { try { const resp = await axios.get('http://127.0.0.1:8000/api/v2/get'); const newData = resp.data[0]; // 仅当新旧值不一致时更新state if (!deepEqual(newData, Data)) { setData(newData); } } catch (err) { console.error('请求失败', err); } }; // 组件挂载时先请求一次 fetchData(); // 每3秒轮询一次,可按需调整间隔时间 const timer = setInterval(fetchData, 3000); // 组件卸载时清除定时器 return () => clearInterval(timer); // 依赖为空数组,仅组件挂载/卸载时执行 }, []); return ( <div className="App"> <Home data={Data}/> </div> ); } export default App;
如果不需要轮询、仅在特定事件触发时才发起请求,把请求逻辑抽到单独的函数里,在对应的触发事件中调用即可。
内容的提问来源于stack exchange,提问作者Awais khan
相关产品推荐
相关产品推荐

