react 中 useMemo Hook 作用
`useMemo`是一个用于优化性能的重要钩子函数。
一、缓存计算结果
1. 基本原理和语法
1.1 原理
`useMemo`用于在函数组件中缓存计算结果。
1.2 语法
`useMemo`接受两个参数:一个函数包含需要缓存的计算逻辑、一个依赖项数组指定哪些值的变化会触发重新计算。
import React, { useMemo, useState } from "react";
const ExpensiveComponent = () => {
const [count, setCount] = useState(0);
// 一个耗时的计算函数,假设这个计算很复杂,不应该每次渲染都执行
const expensiveCalculation = () => {
console.log("Performing expensive calculation...");
let result = 0;
for (let i = 0; i < 1000000; i++) {
result += i;
}
return result;
};
// 使用useMemo缓存计算结果,只有当count变化时才重新计算
const memoizedResult = useMemo(() => expensiveCalculation(), [count]);
return (
<div>
<p>Count: {count}</p>
<p>Memoized Result: {memoizedResult}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
};
export default ExpensiveComponent;
2. 实际应用场景和效果
2.1 复杂数据处理和转换
例如:用户列表组件,需要对列表进行过滤和排序,可以使用`useMemo`来缓存处理后的结果。
import React, { useMemo, useState } from "react";
const UserListComponent = () => {
const [users, setUsers] = useState([
{ id: 1, name: "John", age: 30 },
{ id: 2, name: "Alice", age: 25 },
// 更多用户数据
]);
const [filterText, setFilterText] = useState("");
// 对用户数据进行过滤的函数,假设这是一个复杂的过滤操作
const filterUsers = (users, filterText) => {
return users.filter((user) => user.name.includes(filterText));
};
// 使用useMemo缓存过滤后的用户数据,只有当users或filterText变化时才重新过滤
const filteredUsers = useMemo(
() => filterUsers(users, filterText),
[users, filterText]
);
return (
<div>
<input
type="text"
value={filterText}
onChange={(e) => setFilterText(e.target.value)}
/>
<ul>
{filteredUsers.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</div>
);
};
export default UserListComponent;
二、优化组件渲染
1. 避免不必要的渲染
1.1 与 React.memo 的关联
import React, { memo, useMemo, useState } from "react";
// 子组件,使用React.memo进行优化
const ChildComponent = memo(({ data }) => {
return <div>{data}</div>;
});
const ParentComponent = () => {
const [count, setCount] = useState(0);
// 使用useMemo缓存计算结果,只有当count变化时才重新计算
const memoizedData = useMemo(() => `Count: ${count}`, [count]);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
<ChildComponent data={memoizedData} />
</div>
);
};
export default ParentComponent;