React 高频面试题深度解析
一、组件通信方案
1. 父子组件通信
父传子:通过 props 传递数据
//子组件
function Child({ message }) {
return <p>{message}</p>;
}
//父组件
function Parent() {
return <Child message="Hello from parent" />;
}
子传父:通过回调函数
function Child({ onButtonClick }) {
return <button onClick={() => onButtonClick('Child data')}>Click</button>;
}
function Parent() {
const handleClick = (data) => {
console.log(data); // 接收子组件数据
};
return <Child onButtonClick={handleClick} />;
}
2. 跨层级组件通信
Context API:
const ThemeContext = React.createContext('light');
function App() {
return (
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}
function Toolbar() {
return <ThemedButton />;
}
function ThemedButton() {
const theme = useContext(ThemeContext);
return <button style={{ background: theme }}>Themed Button</button>;
}
二、性能优化方案
1. React.memo
用于函数组件的浅比较优化:
const MemoComponent = React.memo(function MyComponent(props) {
/* 只在props改变时重新渲染 */
});
2. useMemo & useCallback
function App() {
const [count, setCount] = useState(0);
const expensiveValue = useMemo(() => {
return computeExpensiveValue(count);
}, [count]); // 只有count变化时重新计算
const handleClick = useCallback(() => {
console.log('Click happened');
}, []); // 创建一次后保持引用不变
return <ExpensiveComponent value={expensiveValue} onClick={handleClick} />;
}
三、Hooks 高级用法
- useReducer 替代 useState
const initialState = { count: 0 };
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
default:
throw new Error();
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<>
Count: {state.count}
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
</>
);
}
2. 自定义 Hook
function useWindowSize() {
const [size, setSize] = useState({
width: window.innerWidth,
height: window.innerHeight
});
useEffect(() => {
const handleResize = () => {
setSize({
width: window.innerWidth,
height: window.innerHeight
});
};
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
return size;
}
// 使用示例
function MyComponent() {
const { width, height } = useWindowSize();
return <div>Window size: {width} x {height}</div>;
}
四、虚拟DOM与Diff算法
1. 核心原理
虚拟DOM:轻量级的JavaScript对象,表示真实DOM结构 Diff算法:React通过比较新旧虚拟DOM树的差异,最小化DOM操作
2. 优化策略
同级比较:只比较同一层级的节点 Key优化:列表项必须提供稳定唯一的key 组件类型比较:不同类型组件会直接重建
// 错误示范:缺少key或使用索引作为key
{items.map((item, index) => <Item key={index} {...item} />)}
// 正确示范:使用唯一ID作为key
{items.map(item => <Item key={item.id} {...item} />)}
五、React 18 新特性
1. 并发渲染(Concurrent Rendering)
import { startTransition } from 'react';
// 标记为非紧急更新
startTransition(() => {
setState(newState);
});
2. 自动批处理(Automatic Batching)
// React 17及之前:多次setState会触发多次渲染
setState1();
setState2();
// React 18:自动批处理,只触发一次渲染
setState1();
setState2();
3. 新的Hooks
useId:生成唯一ID
function Checkbox() {
const id = useId();
return (
<>
<label htmlFor={id}>Checkbox</label>
<input id={id} type="checkbox" />
</>
);
}
六、常见陷阱与解决方案
1. 闭包陷阱
function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
const timer = setInterval(() => {
// 错误:始终获取初始count值
setCount(count + 1);
// 正确:使用函数式更新
setCount(prev => prev + 1);
}, 1000);
return () => clearInterval(timer);
}, []); // 依赖数组为空
return <div>{count}</div>;
}
2. 无限渲染循环
function Component() {
const [state, setState] = useState({});
// 错误:每次渲染创建新对象导致无限循环
useEffect(() => {
setState({ ...state });
}, [state]); // state每次都是新对象
// 正确:使用值类型或useMemo优化
const memoizedState = useMemo(() => state, [state.key]);
useEffect(() => {
// 安全操作
}, [memoizedState]);
}
以上内容涵盖了React面试中的高频考点,建议结合具体项目经验理解这些概念,在面试中能更好地展示您的React技术深度。