更好的 React Custom Hooks 结构可以避免 exhaustive-deps 警告?
Better Structure for React Custom Hooks that avoid `exhaustive-deps` warning?
我注意到 React 的 exhaustive-deps 行规则并不总是与 setState 函数或当您抽象出 customHooks 时很好地发挥作用。
例如,如果我有一个像这样的 customHook:
function useValidation(initialThings) {
const [needsValidation, setNeedsValidation] = useState(false);
const [thingsToValidate, setThingsToValidate] = useState<Things[]>(initialThings);
useEffect(() => {
debounceValidateThings(thingsToValidate);
}, [things, debounceValidateThings]);
return {
needsValidation,
setNeedsValidation,
thingsToValidate,
setThingsToValidate,
}
}
我在挂钩之外使用了其中一个 setState 函数:
const validationHook = useValidation(initialThings)
useEffect(() => {
// Add something to validate
validationHook.setThingsToValidate(newThings)
validationHook.setNeedsValidation(true)
}, [newThings]);
我注意到这个 returns 带有详尽细节的警告。它建议我将整个 useValidation
添加到可能导致过度重新渲染的深度。
同时,它不会让我只添加 setState 调用:例如setThingsToValidate
或 setNeedsValidation
仍然建议:
- setState 被添加为 dep,即使它不一定是 (https://reactjs.org/docs/hooks-reference.html#usestate)
- 它建议将整个 useX 挂钩添加到 deps 而不是 useX.setState 这会导致不必要的重新渲染
有没有不涉及 lint 警告的解决方法?或者这里有一个范例来抽象出我缺少的钩子??
这里是:
return {
needsValidation,
setNeedsValidation,
thingsToValidate,
setThingsToValidate,
}
每次挂钩运行时创建一个新对象。然后,当您将该对象用作挂钩依赖项时:
useEffect(() => {
// Add something to validate
validationHook.setThingsToValidate(newThings)
validationHook.setNeedsValidation(true)
}, [newThings, validationHook]);
钩子在每次渲染时都会失效。将此对象列为依赖项是绝对正确的,因为它是一个依赖项。
所以你有几个选择。
您可以记忆返回的对象:
return useMemo(() => ({
needsValidation,
setNeedsValidation,
thingsToValidate,
setThingsToValidate,
}, [
needsValidation,
thingsToValidate,
// eslint should know state setters are stable in this scope
// so they can be omitted
])
现在,除非状态发生变化,否则返回对象的身份将得到保留。这使得使用效果依赖性变得安全。
但我认为更好的方法是解构返回的对象,这样您就可以使用 属性 值。状态设置器应该是稳定的,任何依赖于状态值的东西都需要更新。
const {
needsValidation,
setNeedsValidation,
thingsToValidate,
setThingsToValidate,
} = useValidation(initialThings)
useEffect(() => {
setThingsToValidate(newThings)
setNeedsValidation(true)
}, [newThings, setThingsToValidate, setNeedsValidation]);
或者您可以将返回对象的属性列为挂钩依赖项:
const validationHook = useValidation(initialThings)
useEffect(() => {
// Add something to validate
validationHook.setThingsToValidate(newThings)
validationHook.setNeedsValidation(true)
}, [
newThings,
validationHook.setThingsToValidate,
validationHook.setNeedsValidation,
]);
我注意到 React 的 exhaustive-deps 行规则并不总是与 setState 函数或当您抽象出 customHooks 时很好地发挥作用。
例如,如果我有一个像这样的 customHook:
function useValidation(initialThings) {
const [needsValidation, setNeedsValidation] = useState(false);
const [thingsToValidate, setThingsToValidate] = useState<Things[]>(initialThings);
useEffect(() => {
debounceValidateThings(thingsToValidate);
}, [things, debounceValidateThings]);
return {
needsValidation,
setNeedsValidation,
thingsToValidate,
setThingsToValidate,
}
}
我在挂钩之外使用了其中一个 setState 函数:
const validationHook = useValidation(initialThings)
useEffect(() => {
// Add something to validate
validationHook.setThingsToValidate(newThings)
validationHook.setNeedsValidation(true)
}, [newThings]);
我注意到这个 returns 带有详尽细节的警告。它建议我将整个 useValidation
添加到可能导致过度重新渲染的深度。
同时,它不会让我只添加 setState 调用:例如setThingsToValidate
或 setNeedsValidation
仍然建议:
- setState 被添加为 dep,即使它不一定是 (https://reactjs.org/docs/hooks-reference.html#usestate)
- 它建议将整个 useX 挂钩添加到 deps 而不是 useX.setState 这会导致不必要的重新渲染
有没有不涉及 lint 警告的解决方法?或者这里有一个范例来抽象出我缺少的钩子??
这里是:
return {
needsValidation,
setNeedsValidation,
thingsToValidate,
setThingsToValidate,
}
每次挂钩运行时创建一个新对象。然后,当您将该对象用作挂钩依赖项时:
useEffect(() => {
// Add something to validate
validationHook.setThingsToValidate(newThings)
validationHook.setNeedsValidation(true)
}, [newThings, validationHook]);
钩子在每次渲染时都会失效。将此对象列为依赖项是绝对正确的,因为它是一个依赖项。
所以你有几个选择。
您可以记忆返回的对象:
return useMemo(() => ({
needsValidation,
setNeedsValidation,
thingsToValidate,
setThingsToValidate,
}, [
needsValidation,
thingsToValidate,
// eslint should know state setters are stable in this scope
// so they can be omitted
])
现在,除非状态发生变化,否则返回对象的身份将得到保留。这使得使用效果依赖性变得安全。
但我认为更好的方法是解构返回的对象,这样您就可以使用 属性 值。状态设置器应该是稳定的,任何依赖于状态值的东西都需要更新。
const {
needsValidation,
setNeedsValidation,
thingsToValidate,
setThingsToValidate,
} = useValidation(initialThings)
useEffect(() => {
setThingsToValidate(newThings)
setNeedsValidation(true)
}, [newThings, setThingsToValidate, setNeedsValidation]);
或者您可以将返回对象的属性列为挂钩依赖项:
const validationHook = useValidation(initialThings)
useEffect(() => {
// Add something to validate
validationHook.setThingsToValidate(newThings)
validationHook.setNeedsValidation(true)
}, [
newThings,
validationHook.setThingsToValidate,
validationHook.setNeedsValidation,
]);