面试题答案
一键面试1. React.memo
- 作用:React.memo 是一个高阶组件,用于对函数式组件进行浅比较优化。它会在组件接收到新的 props 时,对新旧 props 进行浅比较,如果 props 没有变化,组件就不会重新渲染。
- 应用场景:适用于纯展示型组件,即组件的渲染结果只依赖于 props,不依赖于自身的 state 或者上下文环境等其他因素。
- 示例:
import React from'react';
const MyComponent = React.memo((props) => {
return <div>{props.value}</div>;
});
export default MyComponent;
在上述示例中,MyComponent
是一个展示 props.value
的组件。使用 React.memo
后,只有当 props.value
发生变化时,组件才会重新渲染。
2. useMemo
- 作用:
useMemo
用于缓存一个值(通常是一个计算结果),只有当它的依赖项发生变化时才会重新计算。它可以避免在每次渲染时都进行不必要的计算,从而提升性能。 - 应用场景:当你有一个复杂的计算,而这个计算结果在某些依赖项没有变化时不需要重新计算的场景。例如,计算一个数组的总和,而数组本身没有变化,就不需要每次渲染都重新计算总和。
- 示例:
import React, { useMemo } from'react';
const MyComponent = ({ largeArray }) => {
const sum = useMemo(() => {
return largeArray.reduce((acc, num) => acc + num, 0);
}, [largeArray]);
return <div>{`Sum: ${sum}`}</div>;
};
export default MyComponent;
在这个例子中,useMemo
缓存了 largeArray
的总和计算结果。只有当 largeArray
发生变化时,才会重新计算 sum
。
3. useCallback
- 作用:
useCallback
用于缓存一个函数,只有当它的依赖项发生变化时才会重新创建函数。这在将函数作为 props 传递给子组件,并且希望避免子组件不必要的重新渲染时非常有用。 - 应用场景:常见于子组件依赖父组件传递的函数,且该函数内部逻辑在组件多次渲染过程中不会改变的场景。比如父组件传递一个点击处理函数给子组件,使用
useCallback
可以确保只有依赖项变化时才重新创建该函数,避免子组件因函数引用变化而不必要地重新渲染。 - 示例:
import React, { useCallback } from'react';
const ChildComponent = ({ onClick }) => {
return <button onClick={onClick}>Click me</button>;
};
const ParentComponent = () => {
const handleClick = useCallback(() => {
console.log('Button clicked');
}, []);
return <ChildComponent onClick={handleClick} />;
};
export default ParentComponent;
在上述代码中,ParentComponent
使用 useCallback
缓存了 handleClick
函数。只要依赖项数组 []
中的值没有变化,handleClick
的引用就不会改变,从而避免 ChildComponent
因函数引用变化而不必要地重新渲染。
结合条件渲染逻辑优化性能
假设我们有一个复杂的 React 组件,内部存在多层嵌套的条件渲染逻辑,依赖于 props 和 state。
import React, { useState, useMemo, useCallback } from'react';
const ComplexComponent = ({ data }) => {
const [filter, setFilter] = useState('all');
const filteredData = useMemo(() => {
if (filter === 'all') {
return data;
} else {
return data.filter(item => item.type === filter);
}
}, [data, filter]);
const handleFilterChange = useCallback((newFilter) => {
setFilter(newFilter);
}, []);
return (
<div>
<select onChange={(e) => handleFilterChange(e.target.value)}>
<option value="all">All</option>
<option value="type1">Type 1</option>
<option value="type2">Type 2</option>
</select>
{filteredData.map(item => (
<div key={item.id}>
{item.name} - {item.type}
</div>
))}
</div>
);
};
export default ComplexComponent;
在这个 ComplexComponent
中:
useMemo
用于缓存filteredData
的计算结果,只有当data
或者filter
变化时才重新计算。useCallback
用于缓存handleFilterChange
函数,避免因函数引用变化导致select
组件不必要的重新渲染。这样结合条件渲染逻辑,有效地提升了组件性能。