我有一个异步事件处理程序,该事件处理程序删除了一个组件,但是此组件正在使用状态来监视事件处理程序的执行状态。事件处理程序是从远程数据库删除项目的模拟。
问题在于,成功删除后,组件将被卸载,因此最终状态更新(表明已完成删除)将触发错误“无法对已卸载的组件执行React状态更新”。
我知道这是经常发生的经典问题,我想知道什么是解决该问题的最佳方法。
完整代码供参考:
import React from "react";
export default function App() {
const [fruits, setFruits] = React.useState(["apple", "pear", "peach"]);
return (
<ul>
{fruits.map((fruit) => (
<Row key={fruit} fruit={fruit} setFruits={setFruits} />
))}
</ul>
);
}
function Row({ fruit, setFruits }) {
const [isDeleting, setIsDeleting] = React.useState(false);
const handleDelete = async () => {
setIsDeleting(true);
try {
await deleteFruit(fruit, setFruits);
} catch (error) {
console.log("An error occured");
}
setIsDeleting(false);
};
return (
<li>
{fruit}
<button onClick={handleDelete} disabled={isDeleting}>
X
</button>
</li>
);
}
async function deleteFruit(fruitToDelete, setFruits) {
// mock remote DB
return new Promise((resolve) => {
setTimeout(() => {
setFruits((fruits) => fruits.filter((f) => f !== fruitToDelete));
resolve();
}, 1000);
});
}
我试图通过记录是否通过useRef和useEffect装入组件来防止该问题。它可以工作,但是我发现它不容易阅读。有没有更明确的方法来实现这种行为?
在组件Row的渲染函数中:
const refIsMounted = React.useRef(true);
React.useEffect(() => {
refIsMounted.current = true;
return () => {
refIsMounted.current = false;
};
}, []);
以及异步事件处理程序:
if (refIsMounted.current) {
setIsDeleting(false);
}
答案 0 :(得分:0)
基于useEffect文档,您可以返回清理功能。
通常,效果会创建需要在使用前清理的资源 组件离开屏幕,例如订阅或计时器ID。去做 这样,传递给useEffect的函数可能会返回清理函数。
所以您的代码将如下所示:
useEffect(()=>{
return ()=>{
setIsDeleting(false);}
},[])
答案 1 :(得分:0)