React高频面试题!

583 阅读2分钟

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 高级用法

  1. 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技术深度。