数据改变后停止执行函数(React, useEffect)



我有一个函数(startLoad()),每次我的一些数据变化(即dataMayChange)时执行。在这个方法中,我想执行一些GraphQL查询(即fireQuery1, fireQuery2,…)。每次当我的dataMayChange改变时,我想停止执行startLoad并从一开始再次执行它。这样,我想防止旧的查询之前,我的dataMayChange已经改变被触发。

下面是我的代码:

React.useEffect(() => {   
startLoad()     
// eslint-disable-next-line
}, [dataMayChange])
const startLoad = async() => {
await fireQuery1
await fireQuery2
await fireQuery3
await fireQuery4
}

有没有人知道我怎么才能实现这个行为?

你正在寻找的是一个标志或信号,你可以提供给startLoad告诉它停止,并在useEffect上清理回调。

您可以定制标志或信号,或使用AbortController。下面是后者的一个例子,但roll-your-own看起来非常相似:

React.useEffect(() => {   
const controller = new AbortController();
startLoad(controller.signal);
return () => {
// This function is called when the data is changing and the
// effect callback is about to be re-run
controller.abort();
};
// eslint-disable-next-line
}, [dataMayChange]);
const startLoad = async (signal) => {
await fireQuery1;
if (signal.aborted) {
return;
}
await fireQuery2;
if (signal.aborted) {
return;
}
await fireQuery3;
if (signal.aborted) {
return;
}
await fireQuery4;
};

这是相当重复的,你可能想把你的动作放在一个数组中并循环它。很难证明fireQuery1等显然只是概念上的占位符,但例如:

const startLoad = async (signal) => {
const tasks = [doThis, doThat, doTheOther, doSomethingElse];
for (const task of tasks) {
if (signal.aborted) {
return;
}
await task(); // You can even keep track of its result to pass to the next if relevant, etc.
}
};

如果这些动作中的任何一个涉及到支持AbortController/AbortSignal的东西(如fetch),你也可以将信号传递给这些东西。

最新更新