gpt4 book ai didi

reactjs - React hooks 中的依赖数组真的需要详尽无遗吗?

转载 作者:行者123 更新时间:2023-12-04 13:53:40 24 4
gpt4 key购买 nike

根据React docs :

every value referenced inside the effect function should also appear in the dependencies array


如果我的效果函数引用了外部作用域中的几个变量,但我只想在其中一个变量发生变化时执行它,为什么我需要在依赖数组中指定所有其他变量?是的,如果其他变量发生变化,闭包将变得陈旧,但我不在乎,因为我还不需要调用该函数。当我关心的变量发生变化时,可以调用具有当时值的新闭包。我错过了什么?
这是一个工作示例(据我所知),其中 useEffect 依赖项数组并不详尽:
import React, { useEffect, useState } from "react";

const allCars = {
toyota: ["camry", "corolla", "mirai"],
ford: ["mustang", "cortina", "model T"],
nissan: ["murano", "micra", "maxima"],
};

function CarList() {
const [cars, setCars] = useState([]);
const [brand, setBrand] = useState("toyota");
const [filterKey, setFilterKey] = useState("");

useEffect(() => {
// I don't want to run this effect when filterKey changes because I wanna wrap that case in a timeout to throttle it.
setCars(allCars[brand].filter(model => model.startsWith(filterKey)));
}, [brand]);

useEffect(() => {
// This effect is only called when filterKey changes but still picks up the current value of 'brand' at the time the function is called.
const timeoutId = setTimeout(() => {
setCars(allCars[brand].filter(model => model.startsWith(filterKey)));
}, 500);
return () => clearTimeout(timeoutId);
}, [filterKey]);

const handleChangeFilterKey = event => {
setFilterKey(event.target.value);
};

return (
<div>
{`${brand} cars`}
<div>Select brand</div>
<input type="radio" value="toyota" checked={brand === "toyota"} onChange={() => setBrand("toyota")} />
<input type="radio" value="ford" checked={brand === "ford"} onChange={() => setBrand("ford")} />
<input type="radio" value="nissan" checked={brand === "nissan"} onChange={() => setBrand("nissan")} />
<div>Filter</div>
<input label="search" value={filterKey} onChange={handleChangeFilterKey} />
<ul>
{cars.map(car => (
<li>{car}</li>
))}
</ul>
</div>
);
}
上面的例子有什么缺陷吗?

最佳答案

是的,你应该一直遵循这个规则,当你发现你的代码因为遵循它而中断时,这意味着没有遵循良好的实践。这就是这条规则的含义,确保你设计好的代码。

我想在您的情况下,代码如下所示:

  const Test = () => {
const [wantToSync] = useState(0)
const [notWantToSync] = useState(0) // notWantToSync also might come from props, i'll use state as example here
useEffect(() => {
fetch('google.com', {
body: JSON.stringify({wantToSync, notWantToSync})
}).then(result => {
// ...
})
}, [wantToSync]) // component is supposed to be reactive to notWantToSync, missing notWantToSync in dep is dangerous
}
notWantToSync被定义为 组件状态 ,该组件应该对其具有反应性,包括 useEffect .如果这不是您想要的, notWantToSync不应该从一开始就是状态。
const Test = () => {
const [wantToSync] = useState(0)
const notWantToSyncRef = useRef(0) // hey I don't want notWantToSync to be reactive, so i put it in useRef
useEffect(() => {
fetch('google.com', {
body: JSON.stringify({wantToSync, notWantToSync: notWantToSyncRef.current})
}).then(result => {
// ...
})
}, [wantToSync, notWantToSyncRef]) // yeah, now eslint doesn't bother me, and notWantToSync doesn't trigger useEffect anymore
}
通常你不需要在 useEffect 中执行 if else 来停止重新渲染,还有其他方法,例如 useMemouseCallback除了 useRef做类似的事情尽管它们具有不同的使用上下文。

我在新的例子中看到了你的挣扎,所以你想要做一个 throttle ,如果 filterKey添加到第一个useEffect dep, throttle 会被打破。我的观点是,当你发现自己处于这样的情况时,通常意味着有更好的实践(eslint 详尽的帮助来识别它),例如,将 throttle 逻辑提取到一个钩子(Hook): https://github.com/streamich/react-use/blob/master/src/useThrottle.ts .
详尽的 deps 并不是必须遵循的东西,它只是确保您的代码设计良好的好习惯。上面的例子证明了

关于reactjs - React hooks 中的依赖数组真的需要详尽无遗吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66432806/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com