我已经使用钩子有一段时间了,我从来不完全理解为什么React会迫使我包含一些我不想在useEffect上使用的依赖项。
--我理解useEffect钩子的“依赖性”的方式
每当这些值发生变化并触发效果时,添加要“侦听”的值。它完美地发挥了简单的效果,比如:
import React, {useEffect, useState} from "react";
interface Props {
id: string
}
const SimpleComponent = (props: Props) => {
const {id} = props;
const [response, setResponse] = useState<object>();
useEffect(() => {
fetch(`https://myexample/${id}`)
.then(response => setResponse(response))
.catch(() => console.log("An error occurs!"))
}, [id])
return <div/>
};然而,还有一些其他的例子没有上面的例子那么简单。在本例中,我们只希望在id更改时触发该效果:
import React, {useEffect} from "react";
interface Props {
id: string
callback: Function
}
const SimpleComponent = (props: Props) => {
const {id, callback} = props;
useEffect(() => {
callback(id)
}, [id]);
return <div/>
};在本例中,我得到警告"React有一个缺失的依赖项“,它建议在依赖项数组上包含‘回调’(选项1)或删除依赖项数组(选项2)。
让我们探讨一下建议:
发现的其他备选办法:
我已经从社区中找到了一些其他的建议,但是他们似乎都没有完成被通缉的行为。(https://stackoverflow.com/a/60327893/8168782)
让我们快速回顾一下这些选项:
选项1:使用空依赖项数组:
它只会在组件挂载时触发,而不是我们想要的。
选项2:在useEffect()中声明函数
在这种情况下,‘回调’是一个通过道具传递的函数,但无论哪种方式,大多数情况下您都不能在效果中声明函数,因为函数在其他地方使用。
选项3:使用useCallback()进行记忆
如果将函数包装在useCallback中,还需要将依赖项包含到useCallback依赖项数组中,这将导致每次依赖项更改时再次触发useCallback,因此也将触发useEffect。
选项4:禁用eslint的警告
没有被考虑,因为我试图理解这个问题,而不是简单地忽略它。
我真的很困惑这个警告,我不知道是否有一些警告是错误的,应该被忽略(似乎是错误的),或者我遗漏了什么。
发布于 2020-09-29 07:08:35
就我个人而言,我总是不遵守那条禁止的规则。由于eslint无法理解您的逻辑内涵,它只能彻底检查闭包中捕获的所有变量,并警告您从dep-list中丢失的变量。但是很多时候,就像在用例中一样,这会导致过度的死亡。这就是我选择的理由。
如果您对useEffect的工作原理有一个清晰的理解,那么禁用这个规则不会带来太大的痛苦。我个人不记得有过这种经历。
第二个解决方案是保留规则,但要绕过它。我给你买了一个,useFn定制钩子:
function useFn(fn) {
const ref = useRef(fn);
ref.current = fn;
function wrapper() {
return ref.current.apply(this, arguments)
}
return useRef(wrapper).current
}这个钩子返回wrapper函数的一个稳定引用,它只是一个调用实际fn的代理,但在重呈现过程中不会改变。
const SimpleComponent = (props: Props) => {
const {id, callback: _callback} = props;
const callback = useFn(_callback)
useEffect(() => {
callback(id)
}, [id, callback]);
return <div/>
};现在,您满足了该规则,同时,您不会触发不必要的useEffect重新运行。
作为一个离题的副词。我还使用useFn钩子来包装传递给子组件道具的函数。
在反应中,传递箭头函数是常用的模式。有时,您有一个昂贵的组件来重新呈现,您可以将它包装起来,然后传递一个React.memo(Component)内联函数,这实际上使回忆录效果失效。useFn来拯救:
<Component onClick={useFn(e => { ... })} />https://stackoverflow.com/questions/64106594
复制相似问题