具有无限调用依赖项的 useEffect
useEffect with dependency called infinitely
我有一个警报,我想在列表中的项目 added/removed 后隐藏在超时函数中。
useEffect 没有清理超时函数,而是以循环结束。
function App() {
const [item, setItem] = useState({
id: "",
name: "",
});
const [list, setList] = useState([]);
const [isEditing, setISEditing] = useState(false);
const [alert, setAlert] = useState({
active: false,
type: "",
});
const addToList = (e) => {
e.preventDefault();
setAlert({ active: true, type: "success" });
let newItem = { id: new Date().getTime().toString(), name: item };
e.preventDefault();
setList([...list, newItem]);
};
const removeFromList = (id) => {
setAlert({ active: true, type: "danger" });
setList(list.filter((item) => item.id !== id));
};
useEffect(() => {
const timeout = setTimeout(() => {
setAlert({ active: false, type: "" });
}, 3000);
return () => clearTimeout(timeout);
}, [alert.active]);
我在下面有一个类似的例子,但是 useEffect 并没有以循环结束,尽管我改变了 useEffect 中的状态。
两者到底有什么区别?
const SingleColor = ({ rgb, weight, index }) => {
const [alert, setAlert] = useState(false);
const hex = rgbToHex(...rgb);
useEffect(() => {
const timeout = setTimeout(() => {
setAlert(false);
}, 3000);
return () => clearTimeout(timeout);
}, [alert]);
return (
<article
className={`color ${index > 10 && "color-light"}`}
style={{ backgroundColor: hex }}
onClick={() => {
setAlert(true);
navigator.clipboard.writeText(hex);
}}
>
<p className="percent-value">{weight}%</p>
<p className="color-value">{hex}</p>
{alert && <p className="alert">Copied to clipboard!</p>}
</article>
);
};
export default SingleColor;
使用 alert.active
依赖项,您要在每次 alert.active
更改时重新触发 useEffect
。在 useEffect
中,您正在为 alert.active
设置一个新值,因此创建了一个无限循环。
您应该直接在 addToList 或 remove from list 函数的末尾调用超时。如果你愿意,你可以将它隔离在一个单独的函数中
const cancelTimeout = () => {
setTimeout(() => setAlert({ active: false, type: "" }), 3000)
}
并在 AddToList
和 removeFromList
的末尾调用 cancelTimeout
我有一个警报,我想在列表中的项目 added/removed 后隐藏在超时函数中。
useEffect 没有清理超时函数,而是以循环结束。
function App() {
const [item, setItem] = useState({
id: "",
name: "",
});
const [list, setList] = useState([]);
const [isEditing, setISEditing] = useState(false);
const [alert, setAlert] = useState({
active: false,
type: "",
});
const addToList = (e) => {
e.preventDefault();
setAlert({ active: true, type: "success" });
let newItem = { id: new Date().getTime().toString(), name: item };
e.preventDefault();
setList([...list, newItem]);
};
const removeFromList = (id) => {
setAlert({ active: true, type: "danger" });
setList(list.filter((item) => item.id !== id));
};
useEffect(() => {
const timeout = setTimeout(() => {
setAlert({ active: false, type: "" });
}, 3000);
return () => clearTimeout(timeout);
}, [alert.active]);
我在下面有一个类似的例子,但是 useEffect 并没有以循环结束,尽管我改变了 useEffect 中的状态。 两者到底有什么区别?
const SingleColor = ({ rgb, weight, index }) => {
const [alert, setAlert] = useState(false);
const hex = rgbToHex(...rgb);
useEffect(() => {
const timeout = setTimeout(() => {
setAlert(false);
}, 3000);
return () => clearTimeout(timeout);
}, [alert]);
return (
<article
className={`color ${index > 10 && "color-light"}`}
style={{ backgroundColor: hex }}
onClick={() => {
setAlert(true);
navigator.clipboard.writeText(hex);
}}
>
<p className="percent-value">{weight}%</p>
<p className="color-value">{hex}</p>
{alert && <p className="alert">Copied to clipboard!</p>}
</article>
);
};
export default SingleColor;
使用 alert.active
依赖项,您要在每次 alert.active
更改时重新触发 useEffect
。在 useEffect
中,您正在为 alert.active
设置一个新值,因此创建了一个无限循环。
您应该直接在 addToList 或 remove from list 函数的末尾调用超时。如果你愿意,你可以将它隔离在一个单独的函数中
const cancelTimeout = () => {
setTimeout(() => setAlert({ active: false, type: "" }), 3000)
}
并在 AddToList
和 removeFromList
cancelTimeout