React Hooks 及状态管理高频面试题

1. React Hooks 基础

Q: 请解释 React Hooks 的设计动机和基本使用规则

A:
设计动机

  1. 解决类组件的"wrapper hell"问题
  2. 使状态逻辑更易于复用和组合
  3. 减少对class的理解成本(不再需要理解this)

核心规则

  1. 只在React函数组件的顶层调用Hooks
    // ✅ 正确
    function MyComponent() {
      const [count] = useState(0);
      useEffect(() => {...});
    }
    
    // ❌ 错误(在条件语句中)
    if (condition) {
      const [count] = useState(0);
    }
    
  2. 只在React函数组件或自定义Hook中调用Hooks

2. useState vs useReducer

Q: 在什么场景下应该选择useReducer而不是useState?

A:
useReducer更适合

  1. 状态逻辑复杂(多个子值相关联)
  2. 下一个状态依赖前一个状态
  3. 需要统一管理状态更新逻辑

典型场景

// 表单状态管理
const initialState = { username: '', password: '' };

function reducer(state, action) {
  switch (action.type) {
    case 'field':
      return { ...state, [action.field]: action.value };
    case 'reset':
      return initialState;
    default:
      return state;
  }
}

function Form() {
  const [state, dispatch] = useReducer(reducer, initialState);
  // ...
}

3. useEffect 深度理解

Q: 如何正确使用useEffect处理异步操作?如何避免内存泄漏?

A:
正确模式

useEffect(() => {
  let isMounted = true;
  
  const fetchData = async () => {
    try {
      const result = await api.getData();
      if (isMounted) setData(result);
    } catch (err) {
      if (isMounted) setError(err);
    }
  };

  fetchData();

  return () => {
    isMounted = false; // 清理标志
  };
}, [dependencies]);

常见错误

  1. 直接使用async函数作为effect函数
    // ❌ 错误用法
    useEffect(async () => {
      const result = await fetchData();
    }, []);
    

4. Context API 性能优化

Q: 使用Context API时如何避免不必要的重新渲染?

A:
优化方案

  1. 拆分Context(分离状态和分发逻辑)
    const UserStateContext = createContext(null);
    const UserDispatchContext = createContext(null);
    
  2. 使用memo记忆化子组件
    const UserProfile = memo(({ user }) => {
      return <div>{user.name}</div>
    });
    
  3. 使用useMemo记忆化提供值
    <UserContext.Provider value={useMemo(() => ({ user }), [user])}>
    

5. Redux 现代实践

Q: 解释Redux Toolkit如何简化传统Redux的使用

A:
简化点

  1. configureStore:自动组合reducer、添加中间件
    const store = configureStore({
      reducer: rootReducer,
      middleware: (getDefaultMiddleware) => [...]
    });
    
  2. createSlice:自动生成action creators和reducer
    const counterSlice = createSlice({
      name: 'counter',
      initialState: 0,
      reducers: {
        increment: state => state + 1
      }
    });
    
  3. createAsyncThunk:简化异步逻辑
  4. 内置Immer:允许直接修改state草案

6. MobX 响应式原理

Q: 解释MobX的响应式工作原理及其与Redux的主要区别

A:
工作原理

  1. 通过@observable标记可观察状态
  2. 自动跟踪状态访问(通过Proxy或defineProperty)
  3. 状态变更时自动触发相关组件更新

与Redux对比

特性 MobX Redux
编程范式 面向对象/响应式 函数式/不可变
学习曲线 较低 较高
样板代码
调试工具 时间旅行有限 完善的时间旅行

7. 自定义Hook设计

Q: 如何设计一个支持防抖的useDebounce Hook?

A:
实现方案

import { useEffect, useState } from 'react';

function useDebounce(value, delay) {
  const [debouncedValue, setDebouncedValue] = useState(value);

  useEffect(() => {
    const timer = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);

    return () => {
      clearTimeout(timer);
    };
  }, [value, delay]);

  return debouncedValue;
}

// 使用示例
function Search() {
  const [query, setQuery] = useState('');
  const debouncedQuery = useDebounce(query, 500);
  
  useEffect(() => {
    // 只在停止输入500ms后触发搜索
    if (debouncedQuery) {
      fetchResults(debouncedQuery);
    }
  }, [debouncedQuery]);
}

8. 状态管理选型

Q: 在React应用中如何选择合适的状态管理方案?

A:
选型指南

  1. Context API

    • 适用:简单全局状态(主题/用户信息)
    • 优点:内置、无需额外依赖
    • 限制:不适合高频更新
  2. Redux

    • 适用:大型应用、需要时间旅行调试
    • 优点:可预测、严格的架构
    • 限制:学习成本高、样板代码多
  3. MobX

    • 适用:中小型应用、偏好OOP风格
    • 优点:开发体验流畅、学习曲线平缓
    • 限制:过度响应式可能导致性能问题
  4. Recoil/Jotai

    • 适用:需要原子状态管理
    • 优点:React原生思维、细粒度更新
    • 限制:生态系统较新

决策树

是否需要共享状态?
 ├─ 否 → useState/useReducer
 └─ 是 → 状态更新频率?
     ├─ 低 → Context API
     ├─ 中 → MobX/Zustand
     └─ 高 → Redux/Recoil
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐