面试题答案
一键面试原理
- React.memo:用于函数组件,通过浅比较 props 来决定组件是否重新渲染。如果前后 props 浅比较结果相同,则不重新渲染组件,从而避免不必要的渲染开销。
- useMemo:缓存一个值,只有当依赖项发生变化时才重新计算该值。它返回一个 memoized 值,在依赖项不变的情况下,始终返回相同的值,减少重复计算。
- useCallback:缓存一个函数,只有当依赖项发生变化时才重新创建该函数。它返回一个 memoized 回调函数,常用于将回调函数传递给子组件,避免子组件因父组件重新渲染而不必要地重新渲染。
区别
- React.memo:作用于组件级别,控制组件整体的渲染。只比较 props,对引用类型的 props 进行浅比较。
- useMemo:用于缓存值,重点在于缓存计算结果,防止不必要的重复计算。
- useCallback:用于缓存函数,确保在依赖项不变时函数引用不变,常用于防止子组件不必要的重新渲染。
适用场景
- React.memo:适用于函数组件,当组件接收的 props 比较简单且不经常变化,通过浅比较 props 能有效减少渲染次数时使用。
- useMemo:当有复杂的计算逻辑,且计算结果依赖于某些值,这些值变化不频繁时,使用 useMemo 缓存计算结果。
- useCallback:当需要将回调函数传递给子组件,且子组件依赖于该函数引用时,使用 useCallback 确保函数引用稳定,避免子组件不必要的重新渲染。
电商应用购物车组件优化
- 商品列表:如果商品列表组件接收的 props 主要是商品数据数组,可将商品列表组件包裹在 React.memo 中。若商品数据数组中的对象结构不深,React.memo 通过浅比较能避免不必要渲染。例如商品基本信息(名称、价格等)变化不大时,组件不会重新渲染。
- 总价计算:使用 useMemo 来缓存总价计算结果。总价计算依赖于购物车中的商品列表,当商品列表变化时重新计算总价。示例代码如下:
import React, { useMemo } from'react';
const Cart = ({ items }) => {
const totalPrice = useMemo(() => {
return items.reduce((acc, item) => acc + item.price * item.quantity, 0);
}, [items]);
return (
<div>
{/* 商品列表等内容 */}
<p>总价: {totalPrice}</p>
</div>
);
};
export default Cart;
- 回调函数:如果购物车组件中有添加商品、删除商品等操作的回调函数,且这些回调函数会传递给子组件(如商品列表中的删除按钮),使用 useCallback 缓存这些回调函数。例如删除商品的回调函数:
import React, { useCallback } from'react';
const Cart = ({ items, removeItem }) => {
const handleRemoveItem = useCallback((itemId) => {
removeItem(itemId);
}, [removeItem]);
return (
<div>
{/* 商品列表,每个商品项的删除按钮传递 handleRemoveItem */}
</div>
);
};
export default Cart;
这样,在依赖项不变的情况下,回调函数引用不变,避免子组件因函数引用变化而重新渲染。