useCallback 钩子会记住函数本身,而不是它的返回值。 useCallback 缓存函数引用
组件内部声明的函数会在每次渲染时重新创建,类似于变量。不同之处在于,它每次都会使用不同的参考进行渲染。所以,
依赖于此函数的 useEffect 将在每次渲染时再次执行:
import React, { useState, useEffect, useCallback } from 'react'; // Parent Component const ParentComponent = () => { const [count, setCount] = useState(0); const [text, setText] = useState(""); // Function declared inside the component const handleClick = () => { setCount(count + 1); }; // useEffect depending on handleClick useEffect(() => { console.log("handleClick changed, running useEffect"); }, [handleClick]); return ( <div> <button onClick={handleClick}>Increment Count</button> <p>Count: {count}</p> <ChildComponent handleClick={handleClick} /> </div> ); }; // Child Component const ChildComponent = React.memo(({ handleClick }) => { console.log("ChildComponent re-rendered"); return <button onClick={handleClick}>Child Increment</button>; }); export default ParentComponent;
子组件也会发生类似的情况:
当我们将一个具有昂贵或“慢”渲染逻辑的组件作为另一个组件的子组件时,每次父组件渲染时,其所有子组件也会重新渲染。
为了防止这些不必要的重新渲染,我们可以使用 React.memo。这个高阶组件会缓存子组件,确保它仅在其 props 实际发生变化时才重新渲染。然而,当将函数作为 props 传递时,有一个微妙的问题,这会导致子进程重新渲染,即使它不应该重新渲染。
函数引用的问题
想象一下我们有一个 SlowComponent 作为 App 的子组件。在 App 中,我们有一个状态会在按钮单击时发生变化,从而触发 App 的重新渲染。尽管我们没有更改 SlowComponent 的 props,但它仍然会在每次点击时重新渲染。
为什么?在每次渲染时,handleClick 函数都会使用新的引用重新创建,React 将其解释为更改后的 prop,导致 SlowComponent 重新渲染。为了解决这个问题,我们使用 useCallback 钩子来跨渲染缓存函数的引用。
使用 useCallback 的解决方案
通过将handleClick包装在useCallback中,我们告诉React仅在特定依赖项发生变化时重新创建它。语法如下:
const cachedFn = useCallback(fn, [dependencies]);
在我们的示例中应用 useCallback
让我们看看如何使用 useCallback 来优化我们的 App 组件:
import React, { useState, useCallback } from "react"; const App = () => { const [count, setCount] = useState(0); const [value, setValue] = useState(""); // Wrapping handleClick with useCallback to cache its reference const handleClick = useCallback(() => { setValue("Kunal"); }, [setValue]); return ( <div> <button onClick={() => setCount(count + 1)}>Increment Count</button> <p>Count: {count}</p> <SlowComponent handleClick={handleClick} /> </div> ); }; const SlowComponent = React.memo(({ handleClick }) => { // Intentially making the component slow for (let i = 0; i < 1000000000; i++) {} console.log("SlowComponent re-rendered"); return <button onClick={handleClick}>Click me in SlowComponent</button>; }); export default App;
何时使用 useCallback
以上是理解 Reactjs 中的 useCallback的详细内容。更多信息请关注PHP中文网其他相关文章!