1、什么是 JSX?为什么要使用?
答:JSX是React中用于描述UI的一种扩展语法,它允许我们在JS中书写类HTML的结构。本质上JSX是React.createElement的语法糖,最终会被 Babel 编译成纯 JavaScript 函数调用。
JSX 的优点:
- 可读性:像写 HTML 一样写组件结构,更直观,更清晰;
- 组件化开发友好:模版和逻辑写在一起,便于组织组件;
- 强类型支持:配合
TypeScript使用,能提供更好的开发体验; - 支持
JS表达式:{}包裹后可直接写变量、函数、三元表达式等逻辑; - 工具链生态丰富:JSX 与 Babel、ESlint 等无缝集成,方便做编译、提示和格式化。
2、useCallback和useMemo的区别?
答:useMemo用来缓存计算结果,避免在依赖没变化时重新计算;useCallback是缓存函数的引用,防止函数因为组件重新渲染而重复重建。它们都用于性能优化,前者优化值计算,后者优化函数传递,尤其在传递给子组件时很有用。
useMemo:缓存值(结果)
// 当 data 不变时,不会重新执行 heavyCalculation()
const expensiveValue = useMemo(() => {
return heavyCalculation(data); // 耗时操作
}, [data]);
useCallback:缓存函数(引用)
// 防止每次渲染都创建一个新函数,尤其在传给子组件时,避免不必要的 re-render
const handleClick = useCallback(() => {
console.log('Clicked!');
}, []);
3、React.memo 如何工作?是否可以比较深层对象?
答:React.memo是React提供的一个高阶组件,用于对函数组件进行性能优化。
React.memo会对传入的props进行浅比较(shallow comparison)。- 如果前后
props没有变化,就跳过重新渲染,直接复用上次的渲染结果。 - 它只对
props层面进行优化,不关心组件内部的state或context。 - 可以传递第二个参数,一个自定义比较函数。
4、React 中如何避免不必要的重新渲染?
- 使用
React.memo用于组件
- 作用:缓存函数组件的渲染结果,当 props 没变时跳过重新渲染。
- 适用场景:纯展示组件、接收固定 props 的子组件
const MyComponent = React.memo(function MyComponent({ name }) {
return <div>{name}</div>;
});
- 使用
useMemo(缓存计算结果)
- 作用:缓存一个计算过程(如复杂计算或依赖于 props 的列表过滤等),避免每次渲染都重复计算。
- 注意:仅在性能瓶颈处使用,滥用反而有开销。
const filteredList = useMemo(() => {
return list.filter(item => item.visible);
}, [list]);
- 使用
useCallback(缓存函数引用)
- 作用:防止每次组件渲染都创建新的函数引用,传递给子组件时尤其重要。
// 如果将函数作为 props 传给 React.memo 包裹的子组件,不加 useCallback 会导致子组件每次都重新渲染。
const handleClick = useCallback(() => {
// do something
}, [deps]);
- 父组件中避免不必要的
state/props更新
- 例子:不要频繁 setState 引起全量更新;按需拆分 state。
// bad: 会触发组件重渲染,即使 b 没变
setState({ a: 1, b: 2 });
- 使用 key 正确管理列表渲染
- React 依赖 key 区分 DOM 节点,不稳定的 key(如 index)会导致重复渲染 DOM。
- 避免匿名函数、对象、数组直接写在 JSX 中
- 每次 render 都会新建引用,影响 React.memo、useEffect 的依赖比较。
- 合理拆分组件
- 将大型组件拆成多个小组件,独立控制渲染范围,减少重渲染影响。