我有一个自定义钩子,负责在应用程序初始化时从后端获取一些与用户相关的数据,并将其存储在多个组件所需的全局状态中。数据获取是从钩子内部的useEffect触发的,而且由于多个组件(在同一个视图中呈现)都在调用钩子来访问数据,所以useEffect被多次触发,因此调用API的次数与调用钩子的次数一样多。
下面是自定义钩子内部所发生的事情的简化版本:
const useMyCustomHook = () => {
const [user] = useAuthState(auth); // hook for accessing firebase user
const [data, setData] = useRecoilState([]); // using Recoil state-management lib for global state
useEffect(() => {
if (!user || data.length) return;
const fetchData = async () => {
const apiData = await APICall(someAPIURL);
setData(apiData);
};
}, [user, data]);
return { data };
};这些数据可以通过以下方式在几个组件中访问:
const { data } = useMyCustomHook();因此,基本上,如果数据处于状态,useEffect中的useEffect语句可以防止API调用,但是,由于初始化时,useEffect多次触发(因为调用它的组件同时在屏幕上),每个调用都会触发一个async调用,而该调用在其他组件触发相同效果之前还没有完成,因此会多次调用该API,因为之前的调用还没有填充状态。
有什么办法可以避免这种情况呢?是否有一种方法可以让其他使用钩子的组件知道初始的API是'inProgress‘之类的?
如有任何建议,敬请见谅。非常感谢。
发布于 2022-03-23 20:39:04
我会添加一个状态来跟踪获取状态,并将一个useEffect放在所述状态上。在取取状态上设置一个diff useEffect将防止它在不需要时多次触发。
const useMyCustomHook = () => {
const [user] = useAuthState(auth); // hook for accessing firebase user
const [needFetching, setNeedFetching] = useState(false);
const [data, setData] = useRecoilState([]); // using Recoil state-management lib for global state
useEffect(() => {
if (!user || data.length || needFetching) return;
setNeedFetching(true);
}, [user, data]);
// this only trigger when needFetching state is changed
useEffect(() => {
if (!needFetching) return;
const fetchData = async () => {
const apiData = await APICall(someAPIURL);
setData(apiData);
needFetching(false);
};
}, [needFetching]);
return { data };
};https://stackoverflow.com/questions/71593360
复制相似问题