介绍
useMemo
Hook 是一个用于优化 React 应用程序性能的 Hook。它允许你在渲染期间缓存值,以便在下一次渲染时可以重用它们。
当你使用 useMemo
Hook时,它会在渲染期间计算一个值,并将其缓存起来。如果在下一次渲染时,它检测到输入值没有发生变化,它就会返回缓存的值,而不是重新计算它。这样可以极大地提高应用程序的性能。
语法
const cachedValue = useMemo(calculateValue, dependencies)
它接受两个参数:一个是要计算的函数,另一个是一个依赖数组,数组中的值会被用来比较,如果数组中的值没有发生变化,则不会重新计算,而是直接返回之前计算的结果。
useMemo
和 useCallbac
Hook 很相似。主要的区别是 useMemo
返回一个被记忆的引用值(对象、数组),而useCallback
返回一个被记忆的函数。您可以在使用 useCallback 节中了解更多有关信息。
问题
useMemo
钩子可用于防止昂贵的、资源密集型函数不必要地运行。
在这个例子中,我们有一个每次渲染都会运行的昂贵函数。当更改计数或添加 todo
时,您会注意到执行延迟。
一个性能不佳的函数。每次渲染都会运行 expensiveCalculation
函数:
import { useState } from "react";
import ReactDOM from "react-dom/client";
const App = () => {
const [count, setCount] = useState(0);
const [todos, setTodos] = useState([]);
const calculation = expensiveCalculation(count);
const increment = () => {
setCount((c) => c + 1);
};
const addTodo = () => {
setTodos((t) => [...t, "New Todo"]);
};
return (
<div>
<div>
<h2>My Todos</h2>
{todos.map((todo, index) => {
return <p key={index}>{todo}</p>;
})}
<button onClick={addTodo}>Add Todo</button>
</div>
<hr />
<div>
<button onClick={increment}> Count </button> {count}
<h2>Expensive Calculation</h2>
{calculation}
</div>
</div>
);
};
const expensiveCalculation = (num) => {
console.log("Calculating...");
for (let i = 0; i < 1000000000; i++) {
num += 1;
}
return num;
};
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
解决方案
为了解决这个性能问题,我们可以使用 useMemo
Hook 来记忆 expensiveCalculation
函数。这将导致该函数仅在需要时运行。
我们可以用 useMemo
包装昂贵的函数调用。
useMemoHook
接受第二个参数来声明依赖关系。只有当其依赖项发生变化时,昂贵的函数才会运行。
在下面的示例中,只有当 count
改变时,昂贵的函数才会运行,而不是添加 todo
时。
使用 useMemo
Hook 的性能示例:
import { useState, useMemo } from "react";
import ReactDOM from "react-dom/client";
const App = () => {
const [count, setCount] = useState(0);
const [todos, setTodos] = useState([]);
const calculation = useMemo(() => expensiveCalculation(count), [count]);
const increment = () => {
setCount((c) => c + 1);
};
const addTodo = () => {
setTodos((t) => [...t, "New Todo"]);
};
return (
<div>
<div>
<h2>My Todos</h2>
{todos.map((todo, index) => {
return <p key={index}>{todo}</p>;
})}
<button onClick={addTodo}>Add Todo</button>
</div>
<hr />
<div>
Count: {count}
<button onClick={increment}>+</button>
<h2>Expensive Calculation</h2>
{calculation}
</div>
</div>
);
};
const expensiveCalculation = (num) => {
console.log("Calculating...");
for (let i = 0; i < 1000000000; i++) {
num += 1;
}
return num;
};
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
使用 useMemoHook
后,添加 todo
时不会运行 expensiveCalculation
。
评论 (0)