面试题答案
一键面试1. 使用 React.memo
React.memo
是一个高阶组件,它可以对函数式组件进行浅比较,当 props 没有变化时,阻止组件重新渲染。
import React from 'react';
// 定义数据项组件
const Item = React.memo(({ data, shouldShow }) => {
return shouldShow && <div>{data}</div>;
});
const BigList = () => {
const largeData = Array.from({ length: 1000 }, (_, i) => `Item ${i}`);
const [state, setState] = React.useState({});
const handleToggle = (index) => {
setState((prevState) => ({
...prevState,
[index]:!prevState[index]
}));
};
return (
<div>
{largeData.map((data, index) => (
<div key={index}>
<button onClick={() => handleToggle(index)}>
Toggle {index}
</button>
<Item data={data} shouldShow={state[index] || false} />
</div>
))}
</div>
);
};
export default BigList;
2. 使用 shouldComponentUpdate
(类组件)
在类组件中,shouldComponentUpdate
方法允许我们手动控制组件是否应该重新渲染。
import React, { Component } from'react';
class Item extends Component {
shouldComponentUpdate(nextProps) {
return this.props.data!== nextProps.data || this.props.shouldShow!== nextProps.shouldShow;
}
render() {
const { data, shouldShow } = this.props;
return shouldShow && <div>{data}</div>;
}
}
class BigList extends Component {
constructor(props) {
super(props);
this.state = {};
this.handleToggle = this.handleToggle.bind(this);
}
handleToggle(index) {
this.setState((prevState) => ({
...prevState,
[index]:!prevState[index]
}));
}
render() {
const largeData = Array.from({ length: 1000 }, (_, i) => `Item ${i}`);
return (
<div>
{largeData.map((data, index) => (
<div key={index}>
<button onClick={() => this.handleToggle(index)}>
Toggle {index}
</button>
<Item data={data} shouldShow={this.state[index] || false} />
</div>
))}
</div>
);
}
}
export default BigList;
3. 使用虚拟列表
对于超大数据量的列表,可以使用虚拟列表技术,例如 react - virtualized
或 react - window
。
以 react - window
为例:
import React from'react';
import { FixedSizeList } from'react - window';
const Item = React.memo(({ index, data, shouldShow }) => {
return shouldShow && <div>{data[index]}</div>;
});
const BigList = () => {
const largeData = Array.from({ length: 10000 }, (_, i) => `Item ${i}`);
const [state, setState] = React.useState({});
const handleToggle = (index) => {
setState((prevState) => ({
...prevState,
[index]:!prevState[index]
}));
};
const rowCount = largeData.length;
const rowHeight = 35;
return (
<div>
<FixedSizeList
height={400}
rowCount={rowCount}
rowHeight={rowHeight}
width={300}
>
{({ index }) => (
<div>
<button onClick={() => handleToggle(index)}>
Toggle {index}
</button>
<Item index={index} data={largeData} shouldShow={state[index] || false} />
</div>
)}
</FixedSizeList>
</div>
);
};
export default BigList;
4. 减少不必要的重新渲染范围
- 确保
state
的更新粒度最小化,避免不必要地触发父组件重新渲染,进而影响子列表组件。 - 使用
useCallback
和useMemo
来缓存函数和值,防止因为父组件重新渲染导致子组件依赖的函数或值变化而触发不必要的重新渲染。例如:
import React, { useCallback, useMemo } from'react';
const Item = React.memo(({ data, shouldShow }) => {
return shouldShow && <div>{data}</div>;
});
const BigList = () => {
const largeData = Array.from({ length: 1000 }, (_, i) => `Item ${i}`);
const [state, setState] = React.useState({});
const handleToggle = useCallback((index) => {
setState((prevState) => ({
...prevState,
[index]:!prevState[index]
}));
}, []);
const listItems = useMemo(() => {
return largeData.map((data, index) => (
<div key={index}>
<button onClick={() => handleToggle(index)}>
Toggle {index}
</button>
<Item data={data} shouldShow={state[index] || false} />
</div>
));
}, [largeData, state, handleToggle]);
return (
<div>
{listItems}
</div>
);
};
export default BigList;