反应异步事件处理程序。安全的方式
React async event handler. The safe way
想象一个简单的 React 组件
const Upload: React.FC = () => {
const [done, setDone] = useState(false)
const upload = async () => {
await doSomeAsyncStuffHere()
setDone(true)
}
if(done) {
return <div>success</div>
}
return (
<button onClick={upload}>upload</button>
)
}
乍一看还不错。但是如果上传功能需要很长时间才能完成怎么办?如果用户导航到另一个视图并且组件被卸载怎么办?当异步任务完成时,将导致未安装组件的状态更新。这是一个空操作并且可能是内存泄漏。我应该怎么做才能预防它?
一种解决方法是创建一个 ref
并在卸载组件时将其设置为 false
,并在组件中设置异步代码的结果之前对此进行检查状态。
例子
const Upload: React.FC = () => {
const isMounted = useRef(true);
const [done, setDone] = useState(false)
const upload = async () => {
await doSomeAsyncStuffHere()
if (isMounted.current) {
setDone(true)
}
}
useEffect(() => {
return () => {
isMounted.current = false;
};
}, []);
if(done) {
return <div>success</div>
}
return (
<button onClick={upload}>upload</button>
)
}
想象一个简单的 React 组件
const Upload: React.FC = () => {
const [done, setDone] = useState(false)
const upload = async () => {
await doSomeAsyncStuffHere()
setDone(true)
}
if(done) {
return <div>success</div>
}
return (
<button onClick={upload}>upload</button>
)
}
乍一看还不错。但是如果上传功能需要很长时间才能完成怎么办?如果用户导航到另一个视图并且组件被卸载怎么办?当异步任务完成时,将导致未安装组件的状态更新。这是一个空操作并且可能是内存泄漏。我应该怎么做才能预防它?
一种解决方法是创建一个 ref
并在卸载组件时将其设置为 false
,并在组件中设置异步代码的结果之前对此进行检查状态。
例子
const Upload: React.FC = () => {
const isMounted = useRef(true);
const [done, setDone] = useState(false)
const upload = async () => {
await doSomeAsyncStuffHere()
if (isMounted.current) {
setDone(true)
}
}
useEffect(() => {
return () => {
isMounted.current = false;
};
}, []);
if(done) {
return <div>success</div>
}
return (
<button onClick={upload}>upload</button>
)
}