在React应用程序中,我想让一个函数启动一系列异步调用,然后能够在这些调用运行时更改可用于这些调用的状态。例如,我将让用户启动对5个数据文件的检索,这些数据文件可以在后台运行并耗时数分钟,但可以为他们提供中止该过程或减少文件总数的选项。
这里是关于它的外观的一个想法,但不幸的是,这种模式似乎不起作用:
function App() {
const [halt, setHalt] = useState(false);
return (
...
<button onClick={() => longProcess(halt)}>Start</button>
<button onClick={() => setHalt(true)}>Stop</button>
...
);
}
async function longProcess(halt) {
for (const fileid of files_to_get) {
// For example, halt if the user clicks the Stop button during execution
if (halt) break;
await getDataFile(fileid);
}
}
理想情况下,我想使用纯功能组件,并允许异步功能供多个组件使用。所以我一直在使用React Hooks。我已经提出了3个解决方案,但没有一个完全符合要求:
this.state
将异步更新
useRef()
是a suggested option
我想知道是否有类似于第三个示例的简洁方法,我只是在有限的React经验中没有遇到过。其他建议也欢迎!
答案 0 :(得分:1)
要具有可重用的功能,我将在挂钩中对其进行定义。
以下提议使用useState
执行该功能。当值更改时,我们需要useState
来触发渲染。此值将从useEffect
内部调用该函数。
它还使用useRef
,以便进程可以启动并稍后读取其值,该值在执行期间可能已更改。
const App = () => {
const { startProcess, stopProcess } = useLongProcess();
return (
<Fragment>
<button onClick={startProcess}>Start</button>
<button onClick={stopProcess}>Stop</button>
</Fragment>
);
};
const useLongProcess = () => {
const stop = useRef(false);
const [start_process, setStartProcess] = useState(false);
useEffect(() => {
if (!start_process) {
return;
}
const longProcess = async () => {
for (const fileid of files_to_get) {
if (stop.current) break;
await getDataFile(fileid);
}
};
longProcess();
}, [start_process]);
return {
startProcess: () => setStartProcess(true),
stopProcess: () => {
stop.current = true;
}
};
};
答案 1 :(得分:0)
现在,一旦调用halt
函数内的longProcess
状态,就无法对其进行更新。因此,您可以使用某些global
对象来更新状态,但这不是最佳实践。
因此,也许看一下React的useCallback
和其他钩子,也许将循环更改为递归调用这些钩子之一,这样也许可以帮助更新状态。希望这会有所帮助,即使我现在还不知道解决方案。