面试题答案
一键面试处理列表项的动态高度
- 测量并缓存高度
在渲染列表项之前,测量每个列表项的高度,并将其缓存起来。可以在数据加载阶段或者首次渲染时进行测量。例如,使用
ref
来获取列表项元素的实际高度:
import React, { useRef } from'react';
const Item = ({ data }) => {
const itemRef = useRef(null);
const measureHeight = () => {
if (itemRef.current) {
const height = itemRef.current.offsetHeight;
// 这里可以将height存储到一个全局或者组件状态中
}
};
React.useEffect(() => {
measureHeight();
}, []);
return <div ref={itemRef}>{data}</div>;
};
- 使用自适应高度算法
有些虚拟化库支持动态高度算法,如
react - virtualized
的AutoSizer
组件结合List
组件。AutoSizer
会自动测量父容器的尺寸,List
组件则根据这些尺寸和列表项的高度计算可见区域。
优化数据更新时的渲染性能
- 使用
shouldComponentUpdate
或React.memo
对于类组件,通过重写shouldComponentUpdate
方法,根据数据变化情况决定是否重新渲染。例如:
class MyListItem extends React.Component {
shouldComponentUpdate(nextProps) {
return this.props.data!== nextProps.data;
}
render() {
return <div>{this.props.data}</div>;
}
}
对于函数组件,使用React.memo
进行浅比较优化。只有当组件的props
发生变化时才重新渲染:
const MyListItem = React.memo(({ data }) => {
return <div>{data}</div>;
});
- 批量更新
在React中,数据更新可能会导致多次渲染。可以使用
unstable_batchedUpdates
(React 18之前)或者React 18自动批量更新机制,将多个状态更新合并为一次渲染。例如:
import React, { useState, useEffect } from'react';
import ReactDOM from'react-dom';
import { unstable_batchedUpdates } from'react-dom';
const App = () => {
const [count1, setCount1] = useState(0);
const [count2, setCount2] = useState(0);
const handleClick = () => {
// React 18之前使用unstable_batchedUpdates
// unstable_batchedUpdates(() => {
// setCount1(count1 + 1);
// setCount2(count2 + 1);
// });
// React 18自动批量更新
setCount1(count1 + 1);
setCount2(count2 + 1);
};
return (
<div>
<p>Count1: {count1}</p>
<p>Count2: {count2}</p>
<button onClick={handleClick}>Increment</button>
</div>
);
};
ReactDOM.render(<App />, document.getElementById('root'));
- 使用
useCallback
和useMemo
useCallback
用于缓存函数,避免在每次渲染时重新创建,从而减少不必要的子组件重新渲染。例如:
const Parent = () => {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => {
setCount(count + 1);
}, [count]);
return <Child onClick={handleClick} />;
};
const Child = React.memo(({ onClick }) => {
return <button onClick={onClick}>Click me</button>;
});
useMemo
用于缓存计算结果,只有当依赖项发生变化时才重新计算。比如:
const Parent = () => {
const [a, setA] = useState(1);
const [b, setB] = useState(2);
const result = useMemo(() => {
return a + b;
}, [a, b]);
return <div>{result}</div>;
};