ReactJS:如何检测其他组件的数值变化并与旧值对比,避免不必要的API调用
问题根因
你当前的实现逻辑里,useEffect将props.id作为依赖项,只要props.id(也就是点击Click Me按钮修改的数值)发生变化,useEffect就会自动执行触发接口请求,这是不符合预期的核心原因,额外引入的usePrevious没有起到拦截作用,反而被加入依赖项进一步放大了问题。
修复方案
按照你的需求,只有点击Call API按钮才触发请求,完全不需要用useEffect来监听参数变化,调整逻辑如下:
把接口请求逻辑封装为独立函数,通过useImperativeHandle暴露给父组件,父组件点击Call API按钮时主动调用该函数即可,此时拿到的props.id就是当前最新的数值,完全符合要求。
调整后的GetAPIData组件代码
import { useState, useImperativeHandle, forwardRef } from 'react'; import axios from 'axios'; const GetAPIData = forwardRef((props, ref) => { const [chars, setChars] = useState([]); // 暴露请求方法给父组件 useImperativeHandle(ref, () => ({ fetchData: () => { axios .get(`https://rickandmortyapi.com/api/character/?page=${props.id}`) .then((res) => { setChars(res.data.results); }) .catch((err) => { alert(err.message); }); } })); return ( <div className="container"> <h3> <span>Achtung,</span> ein Trend geht um </h3> </div> ); }); export default GetAPIData;
父组件对应调整
// 父组件内创建ref关联子组件 const apiRef = useRef(); // 存储Click Me按钮对应的数值 const [count, setCount] = useState(1); // Click Me按钮点击逻辑,仅修改count const handleClickCount = () => setCount(prev => prev + 1); // Call API按钮点击逻辑,主动调用子组件的请求方法 const handleCallApi = () => apiRef.current?.fetchData(); // 组件渲染 return ( <> <GetAPIData ref={apiRef} id={count} /> <button onClick={handleClickCount}>Click Me</button> <button onClick={handleCallApi}>Call API</button> </> )
如果不想用ref调用的方式,也可以在父组件多维护一个requestPage状态:点击Click Me仅修改count,点击Call API时才把count赋值给requestPage,把requestPage作为props传给GetAPIData,此时useEffect依赖requestPage即可,只有requestPage变化时才会发请求。
内容的提问来源于stack exchange,提问作者TMA
相关产品推荐
相关产品推荐

