我可以在useEffect中调用另一个单独的函数吗?
我在useEffect中调用了另一个函数,但在保存文件后,它会自动将该函数添加到useEffect的数组参数中。
请参阅下面的代码以获得正确的理解。
保存文件前:
useEffect(() => {
getData()
console.log("useEffect ran...");
}, [query]);
function getData() {
fetch(`https://jsonplaceholder.typicode.com/${query}`)
.then(response => response.json())
.then(json => setData(json));
}
保存文件后:
useEffect(() => {
getData();
console.log("useEffect ran...");
}, [getData, query]);
function getData() {
fetch(`https://jsonplaceholder.typicode.com/${query}`)
.then(response => response.json())
.then(json => setData(json));
}
它一次又一次地运行。
6条答案
按热度按时间zed5wv101#
TL;DR使用
useCallback()
首先,使用函数作为依赖项是非常危险的,如果那个函数导致了状态的改变,那么后续的重新渲染就会再次调用这个函数(通过useEffect)......无限循环就开始了。
您可以做的一件事,正如许多人在这里建议的那样,是在useEffect()方法本身中创建函数。
或者干脆
话虽如此,有时候你还是想在useEffect外声明函数,以便代码重用。这次你需要确保它不会在每次渲染时重新创建。为此,你可以选择
1.在组件外声明函数--这迫使您将所有变量作为参数传递……这很痛苦
1.将其 Package 在
useMemo()
或useCallback()
中这里有一个例子
li9yvcax2#
因为你在React组件中声明了
getData
函数,所以它会在每次渲染时重新创建,因此效果的依赖关系会在每次渲染时改变。这就是为什么效果会在每次渲染时执行的原因。为了防止这种情况发生,您应该在组件外部声明
getData
函数,然后传递查询,如下所示:P.S:我不确定eslint插件是否会在这样做时自动将getData添加到依赖项中,但即使这样做也不会有什么坏处。
mhd8tkvw3#
公认的答案在某种程度上是误导性的。在组件内部定义函数显然会在每次渲染时重新创建。但这并不意味着当使用内部useEffect钩子时,它会在每次渲染中重新调用。
在保存文件代码后,您正在监视getData的关键问题。由于它在每次渲染时重新创建,因此useEffect将其作为更改接受,从而导致您在每次渲染时重新运行。简单的解决方法是不监视getData。
但很明显,正如公认的答案所建议的那样,更好的做法是将函数分离到组件之外,这样它就不会在每次渲染时重新创建。
坦率地说,如果我是你,我不会只为fetch定义函数:
u4dcyp6a4#
你也可以使用
useRef
来创建一个ref,并将函数定义放在那里,然后使用ref.current()
调用它。即使是React也支持使用ref作为示例变量。useRef
返回一个可变的ref对象,其.current
属性被初始化为传入的参数(initialValue
)。返回的对象将在组件的整个生存期内持续存在。然而,
useRef()
的用处远不止ref
属性,它可以方便地保存任何可变值,就像在类中使用示例字段一样。重要提示:
如果你想在这个方法中使用任何状态变量,那么你必须创建一个可变对象(就像另一个ref),它将包含state的最新值,就像你直接引用一个state变量一样,那么它将引用在方法创建时创建的旧值/默认值。要了解更多信息,你可以refer here。
useCallback
方法也是如此。zysjyyx45#
如果将
getData
函数移动到useEffect
内部,则不必将其作为依赖项包含在内,并且useEffect
仅在query
更改时运行。sh7euo9m6#
尝试将getData函数 Package 在useCallback钩子内,并将其放在组件外,这样,当getData被调用时,它将不会一直返回新函数,因此它将阻止组件重新呈现