Skip to content

100道高频React面试题 - 完整题库精选

基础概念 (1-20题)

1. React是什么?它的主要特点是什么?

答案:
React是Facebook开发的JavaScript库,用于构建用户界面。

主要特点:
1. 声明式: 描述UI应该是什么样
2. 组件化: 可复用的组件
3. Virtual DOM: 提升性能
4. 单向数据流: 数据自上而下流动
5. JSX语法: JavaScript + XML
6. Learn Once, Write Anywhere: 可用于Web/Native/VR

2. JSX是什么?它是如何工作的?

答案:
JSX是JavaScript XML的语法扩展。

工作原理:
1. Babel编译JSX为React.createElement调用
2. createElement创建React Element (Virtual DOM)
3. React渲染Virtual DOM到真实DOM

示例:
<div>Hello</div>
↓ 编译为
React.createElement('div', null, 'Hello')

3. 组件和元素的区别?

答案:
元素(Element):
- React.createElement的返回值
- 普通JavaScript对象
- 描述DOM节点或组件实例
- 不可变的

组件(Component):
- 函数或类
- 接收props返回元素
- 可以有状态和生命周期
- 可复用的

关系: 组件返回元素,元素描述UI

4. 函数组件和类组件的区别?

答案:
函数组件:
- 简单的JavaScript函数
- 使用Hooks管理状态
- 没有this
- 性能更好
- 推荐使用

类组件:
- ES6类
- 使用this.state和生命周期方法
- 有this绑定问题
- 较复杂
- 逐渐被函数组件替代

5. Props和State的区别?

答案:
Props:
- 父组件传递给子组件
- 只读,不可修改
- 用于组件间通信

State:
- 组件内部状态
- 可以通过setState/useState修改
- 触发重新渲染
- 私有的

6. 什么是受控组件和非受控组件?

答案:
受控组件:
- value由React state控制
- onChange更新state
- 单一数据源

非受控组件:
- value由DOM自己管理
- 使用ref访问值
- 类似传统HTML表单

7. React中的key有什么作用?

答案:
作用:
1. 帮助React识别哪些项变化/添加/删除
2. 优化列表渲染性能
3. 保持组件状态稳定

要求:
- 唯一且稳定
- 不建议使用索引(除非静态列表)

8. 为什么不能用索引作为key?

答案:
问题:
1. 列表重排序时索引变化
2. 导致错误的组件复用
3. 可能丢失组件状态
4. 性能优化失效

示例:
[A, B, C] -> [C, A, B]
使用索引: key 0,1,2 -> 0,1,2 (React认为内容变了)
使用ID: key a,b,c -> c,a,b (React知道是移动)

9. 什么是Virtual DOM?

答案:
Virtual DOM是DOM的JavaScript对象表示。

优势:
1. 减少直接DOM操作
2. 批量更新
3. 跨平台能力
4. Diff算法优化

工作流程:
1. 状态变化
2. 创建新Virtual DOM
3. Diff算法比较
4. 最小化更新真实DOM

10. React生命周期有哪些?

答案:
挂载:
- constructor
- getDerivedStateFromProps
- render
- componentDidMount

更新:
- getDerivedStateFromProps
- shouldComponentUpdate
- render
- getSnapshotBeforeUpdate
- componentDidUpdate

卸载:
- componentWillUnmount

错误:
- getDerivedStateFromError
- componentDidCatch

Hooks (21-40题)

21. useState的工作原理?

答案:
1. mount时创建Hook节点,初始化状态
2. 状态存储在Fiber.memoizedState链表
3. setState创建更新对象,加入队列
4. update时处理更新队列,计算新状态
5. 触发重新渲染

特点:
- 异步批量更新
- 支持函数式更新
- dispatch引用稳定

22. useEffect的执行时机?

答案:
执行时机:
- mount: 组件渲染完成后异步执行
- update: 依赖变化后异步执行
- unmount: 执行cleanup

与useLayoutEffect区别:
- useEffect: 异步,不阻塞渲染
- useLayoutEffect: 同步,阻塞渲染

23. useEffect的依赖数组如何工作?

答案:
- 无deps: 每次渲染都执行
- 空deps []: 只在mount时执行
- 有deps: deps变化时执行

比较方式:
- 使用Object.is浅比较
- 对象/数组按引用比较

24. useMemo和useCallback的区别?

答案:
useMemo:
- 缓存计算结果
- 返回值

useCallback:
- 缓存函数引用
- 返回函数

关系:
useCallback(fn, deps) = useMemo(() => fn, deps)

25. useRef的作用?

答案:
作用:
1. 访问DOM节点
2. 保存可变值(不触发渲染)
3. 保持跨渲染的引用

特点:
- .current可变
- 改变不触发渲染
- 引用稳定

26. useContext的使用场景?

答案:
使用场景:
1. 跨层级传递数据
2. 主题切换
3. 用户信息
4. 多语言
5. 全局配置

优势:
- 避免props drilling
- 组件解耦

注意:
- 会导致所有消费者重渲染
- 需要优化拆分Context

27. useReducer vs useState?

答案:
useReducer适用:
- 复杂状态逻辑
- 多个子值
- 状态依赖前一状态
- 需要dispatch稳定引用

useState适用:
- 简单状态
- 独立更新

代码示例:
const [state, dispatch] = useReducer(reducer, initialState);

28. 自定义Hook的规则?

答案:
命名规则:
- 必须以use开头

调用规则:
- 只能在顶层调用
- 只能在函数组件或其他Hook中调用
- 不能在条件/循环中调用

优势:
- 复用状态逻辑
- 分离关注点
- 提取业务逻辑

29. useImperativeHandle的作用?

答案:
作用:
- 自定义暴露给父组件的ref值
- 通常与forwardRef一起使用

示例:
useImperativeHandle(ref, () => ({
  focus: () => inputRef.current.focus(),
  reset: () => inputRef.current.value = ''
}));

场景:
- 封装复杂组件
- 控制暴露的API

30. useLayoutEffect vs useEffect?

答案:
useLayoutEffect:
- 同步执行
- DOM更新后立即执行
- 阻塞渲染
- 用于DOM测量

useEffect:
- 异步执行
- 渲染完成后执行
- 不阻塞渲染
- 用于副作用

选择:
- 需要读取布局 -> useLayoutEffect
- 其他情况 -> useEffect

31. React Hooks的调用顺序为什么重要?

答案:
原因:
- Hooks存储在链表中
- 通过调用顺序关联状态
- 顺序变化导致状态错位

示例(错误):
if (condition) {
  useState(0); // 条件调用会打乱顺序
}

正确:
const [state, setState] = useState(0);
if (condition) {
  setState(1); // 在Hook外使用
}

32. useTransition是什么?

答案:
定义: React 18并发特性,标记非紧急更新

使用:
const [isPending, startTransition] = useTransition();

startTransition(() => {
  setQuery(input); // 低优先级更新
});

场景:
- 搜索输入
- 标签切换
- 路由跳转

33. useDeferredValue的作用?

答案:
作用: 延迟更新值,优先响应用户输入

示例:
const deferredQuery = useDeferredValue(query);

与useTransition对比:
- useTransition: 控制更新
- useDeferredValue: 延迟值

场景:
- 搜索结果
- 大列表渲染

34. useId的使用场景?

答案:
作用: 生成唯一ID,SSR安全

使用:
const id = useId();
<label htmlFor={id}>Name</label>
<input id={id} />

场景:
- 表单关联
- 无障碍属性
- 避免ID冲突

35. useSyncExternalStore是什么?

答案:
作用: 订阅外部store,支持并发特性

使用:
const value = useSyncExternalStore(
  subscribe,
  getSnapshot,
  getServerSnapshot
);

场景:
- 状态管理库
- 浏览器API订阅
- WebSocket数据

36. useInsertionEffect的作用?

答案:
作用: CSS-in-JS库注入样式

特点:
- 在DOM变更前执行
- 早于useLayoutEffect
- 只能在DOM插入时使用

使用:
useInsertionEffect(() => {
  document.head.appendChild(style);
});

场景:
- CSS-in-JS
- 样式库

37. 如何实现自定义useDebounce?

javascript
function useDebounce(value, delay) {
  const [debouncedValue, setDebouncedValue] = useState(value);
  
  useEffect(() => {
    const timer = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);
    
    return () => clearTimeout(timer);
  }, [value, delay]);
  
  return debouncedValue;
}

38. 如何实现useThrottle?

javascript
function useThrottle(value, delay) {
  const [throttledValue, setThrottledValue] = useState(value);
  const lastRan = useRef(Date.now());
  
  useEffect(() => {
    const timer = setTimeout(() => {
      if (Date.now() - lastRan.current >= delay) {
        setThrottledValue(value);
        lastRan.current = Date.now();
      }
    }, delay - (Date.now() - lastRan.current));
    
    return () => clearTimeout(timer);
  }, [value, delay]);
  
  return throttledValue;
}

39. 如何实现usePrevious?

javascript
function usePrevious(value) {
  const ref = useRef();
  
  useEffect(() => {
    ref.current = value;
  }, [value]);
  
  return ref.current;
}

40. 如何实现useLocalStorage?

javascript
function useLocalStorage(key, initialValue) {
  const [value, setValue] = useState(() => {
    const item = localStorage.getItem(key);
    return item ? JSON.parse(item) : initialValue;
  });
  
  const setStoredValue = (newValue) => {
    setValue(newValue);
    localStorage.setItem(key, JSON.stringify(newValue));
  };
  
  return [value, setStoredValue];
}

性能优化 (41-60题)

41. 如何优化React性能?

答案:
1. 使用React.memo避免重渲染
2. useMemo缓存计算结果
3. useCallback缓存函数
4. 代码分割和懒加载
5. 虚拟滚动处理大列表
6. 使用key优化列表
7. 避免内联对象/函数
8. Context优化

42. React.memo的工作原理?

答案:
作用: 对函数组件props做浅比较

原理:
1. 缓存上次渲染结果
2. 新props和旧props浅比较
3. 相等则返回缓存结果
4. 不等则重新渲染

自定义比较:
React.memo(Component, (prevProps, nextProps) => {
  return prevProps.id === nextProps.id;
});

43. 如何避免不必要的重渲染?

答案:
方法:
1. React.memo包裹组件
2. 使用useMemo/useCallback
3. 状态下放
4. 组件拆分
5. children prop模式
6. 避免内联对象/函数

44. 什么是代码分割?

答案:
定义: 将代码拆分成小块,按需加载

实现方式:
1. React.lazy动态导入
2. 路由级分割
3. 组件级分割

示例:
const LazyComponent = React.lazy(() => import('./Component'));

<Suspense fallback={<Loading />}>
  <LazyComponent />
</Suspense>

优势:
- 减少初始加载
- 提升首屏速度
- 按需加载资源

45. 虚拟滚动是什么?

答案:
定义: 只渲染可见区域的列表项

原理:
1. 计算可见区域
2. 只渲染可见项+缓冲项
3. 监听滚动更新

库:
- react-window
- react-virtualized

适用场景:
- 长列表(1000+项)
- 表格
- 聊天记录

46. 如何优化Context性能?

答案:
优化方法:
1. 拆分Context
2. 使用useMemo包装value
3. 使用React.memo隔离消费者
4. 状态分离(provider pattern)

示例:
const value = useMemo(
  () => ({ user, theme }),
  [user, theme]
);

<Context.Provider value={value}>

47. 懒加载图片怎么实现?

javascript
function LazyImage({ src, alt }) {
  const [inView, setInView] = useState(false);
  const ref = useRef();
  
  useEffect(() => {
    const observer = new IntersectionObserver(
      ([entry]) => {
        if (entry.isIntersecting) {
          setInView(true);
          observer.disconnect();
        }
      }
    );
    
    if (ref.current) {
      observer.observe(ref.current);
    }
    
    return () => observer.disconnect();
  }, []);
  
  return (
    <img
      ref={ref}
      src={inView ? src : placeholder}
      alt={alt}
    />
  );
}

48. 如何优化大型表单性能?

答案:
优化策略:
1. 字段级状态管理
2. 使用非受控组件
3. 使用表单库(React Hook Form)
4. 虚拟化长表单
5. 分步骤表单
6. 防抖提交

49. React性能分析工具有哪些?

答案:
工具:
1. React DevTools Profiler
2. Chrome DevTools Performance
3. Lighthouse
4. why-did-you-render
5. React.Profiler API

使用:
<Profiler id="App" onRender={callback}>
  <App />
</Profiler>

50. 什么是Concurrent Mode?

答案:
定义: React 18并发渲染机制

特点:
- 可中断渲染
- 优先级调度
- 自动批处理
- Suspense data fetching

开启:
createRoot(container).render(<App />)

API:
- useTransition
- useDeferredValue
- startTransition

51. 如何优化首屏加载?

答案:
策略:
1. 代码分割
2. 路由懒加载
3. 图片懒加载
4. 预加载关键资源
5. SSR/SSG
6. Tree Shaking
7. 压缩资源
8. CDN加速

52. 什么是Tree Shaking?

答案:
定义: 移除未使用的代码

要求:
- ES6 modules
- 纯函数
- sideEffects配置

webpack配置:
{
  "sideEffects": false
}

优势:
- 减小bundle大小
- 提升加载速度

53. 如何处理组件间的性能隔离?

答案:
方法:
1. React.memo隔离
2. 状态下放
3. Context拆分
4. children prop
5. render props

示例:
function Slow Component({ children }) {
  return (
    <div>
      <ExpensiveComputation />
      {children}
    </div>
  );
}

<SlowComponent>
  <FastComponent /> {/* 不会因父组件重渲染 */}
</SlowComponent>

54. 批量更新是如何工作的?

答案:
React 18:
- 自动批量更新所有更新
- 包括setTimeout、Promise、原生事件

React 17:
- 只批量处理React事件
- 其他需要手动批处理

强制批处理:
import { unstable_batchedUpdates } from 'react-dom';

unstable_batchedUpdates(() => {
  setState1();
  setState2();
});

55. 如何优化条件渲染?

答案:
优化方法:
1. 提前return
2. 使用&&短路
3. 三元运算符
4. 拆分组件
5. useMemo缓存

不推荐:
if (condition) return <ComponentA />
return <ComponentB />

推荐:
return condition ? <ComponentA /> : <ComponentB />

56. 如何优化事件处理器?

答案:
优化方法:
1. useCallback缓存函数
2. 事件委托
3. 使用事件对象池
4. 避免bind

示例:
const handleClick = useCallback((id) => {
  console.log(id);
}, []);

<button onClick={() => handleClick(id)}>

57. 为什么不要在render中创建组件?

答案:
问题:
1. 每次渲染创建新组件
2. 重新挂载,丢失状态
3. 性能开销

错误示例:
function Parent() {
  const Child = () => <div>Child</div>; // 错误!
  return <Child />;
}

正确:
const Child = () => <div>Child</div>;
function Parent() {
  return <Child />;
}

58. 如何优化列表渲染?

答案:
优化方法:
1. 使用稳定key
2. 虚拟滚动
3. 分页/懒加载
4. React.memo包裹item
5. useCallback优化事件

示例:
const ListItem = React.memo(({ item, onClick }) => (
  <div onClick={() => onClick(item.id)}>
    {item.name}
  </div>
));

59. 什么是windowing?

答案:
定义: 虚拟滚动技术,只渲染可见项

库:
- react-window (轻量)
- react-virtualized (功能全)

使用场景:
- 超长列表
- 表格
- 无限滚动

示例:
<FixedSizeList
  height={600}
  itemCount={1000}
  itemSize={35}
>
  {Row}
</FixedSizeList>

60. React.StrictMode的作用?

答案:
作用:
1. 检测不安全生命周期
2. 警告过时API
3. 检测副作用
4. 双重渲染检测

注意:
- 只在开发模式生效
- 会调用两次render

<StrictMode>
  <App />
</StrictMode>

React 19新特性 (61-80题)

61. React 19有哪些新特性?

答案:
1. React Compiler: 自动优化
2. Actions: 简化表单处理
3. use() Hook: 统一异步处理
4. Document Metadata: 原生title/meta
5. ref改进: ref作为普通prop
6. 资源预加载: 新的preload API

62. Server Components是什么?

答案:
定义: 只在服务端运行的React组件

特点:
- 零客户端JavaScript
- 直接访问后端资源
- 减少bundle大小
- 不能使用Hooks
- 不能有交互

与SSR区别:
- SSR生成HTML
- RSC序列化组件树
- RSC不需要hydration

63. React Compiler是什么?

答案:
定义: React 19自动编译优化工具

功能:
- 自动memoization
- 自动useCallback/useMemo
- 减少样板代码
- 性能自动优化

配置:
// babel.config.js
{
  plugins: ['react-compiler']
}

优势:
- 无需手动优化
- 代码更简洁
- 性能提升

64. Actions是什么?

答案:
定义: React 19简化表单处理的新特性

使用:
<form action={handleSubmit}>
  <input name="username" />
  <button type="submit">提交</button>
</form>

function handleSubmit(formData) {
  const username = formData.get('username');
  // 处理提交
}

配合Hooks:
- useFormStatus
- useFormState
- useOptimistic

65. use() Hook是什么?

答案:
定义: 统一处理Promise和Context的Hook

使用:
// 读取Context
const theme = use(ThemeContext);

// 读取Promise
const data = use(fetchData());

特点:
- 可以在条件语句中使用
- 自动Suspense
- 统一异步处理

66. useOptimistic的作用?

答案:
作用: 乐观更新UI

示例:
const [optimisticMessages, addOptimisticMessage] = useOptimistic(
  messages,
  (state, newMessage) => [...state, newMessage]
);

const handleSend = async (message) => {
  addOptimisticMessage(message);
  await sendMessage(message);
};

场景:
- 点赞
- 评论
- 表单提交

67. useFormStatus是什么?

答案:
作用: 获取表单提交状态

使用:
function SubmitButton() {
  const { pending } = useFormStatus();
  
  return (
    <button disabled={pending}>
      {pending ? '提交中...' : '提交'}
    </button>
  );
}

68. useFormState的使用?

答案:
作用: 管理表单状态和服务端反馈

使用:
const [state, formAction] = useFormState(serverAction, initialState);

<form action={formAction}>
  <input name="email" />
  {state.error && <p>{state.error}</p>}
</form>

async function serverAction(prevState, formData) {
  // 验证和处理
  return { error: null, success: true };
}

69. Document Metadata如何使用?

答案:
定义: 在组件中直接设置title和meta

使用:
function BlogPost({ post }) {
  return (
    <>
      <title>{post.title}</title>
      <meta name="description" content={post.excerpt} />
      <article>{post.content}</article>
    </>
  );
}

优势:
- 组件化
- 自动去重
- SSR友好

70. ref作为prop有什么变化?

答案:
React 19:
- ref可以作为普通prop传递
- 不再需要forwardRef

之前:
const Input = forwardRef((props, ref) => (
  <input ref={ref} {...props} />
));

现在:
function Input({ ref, ...props }) {
  return <input ref={ref} {...props} />;
}

71. 资源预加载API有哪些?

答案:
新API:
1. preload: 预加载资源
2. preinit: 预初始化资源
3. preconnect: 预连接

使用:
import { preload, preinit } from 'react-dom';

// 预加载脚本
preload('/script.js', { as: 'script' });

// 预初始化样式
preinit('/styles.css', { as: 'style' });

场景:
- 路由预加载
- 关键资源
- 第三方脚本

72. Suspense有哪些改进?

答案:
React 19改进:
1. 支持data fetching
2. 更好的error boundary
3. Suspense列表
4. 嵌套Suspense优化

使用:
<Suspense fallback={<Loading />}>
  <Component />
</Suspense>

配合:
- React.lazy
- use() Hook
- Server Components

73. Error Boundary有哪些新特性?

答案:
React 19:
- 更好的错误信息
- error.digest支持
- 组件栈信息

使用:
class ErrorBoundary extends Component {
  static getDerivedStateFromError(error) {
    return { hasError: true };
  }
  
  componentDidCatch(error, errorInfo) {
    console.log(error.digest); // 新增
    console.log(errorInfo.componentStack);
  }
}

74. hydration有什么改进?

答案:
改进:
1. 选择性hydration
2. 流式hydration
3. 错误恢复
4. 部分hydration

特点:
- 更快的交互
- 更好的用户体验
- 自动优先级

75. Context有什么改进?

答案:
React 19改进:
1. 自动bailout优化
2. use()读取Context
3. 更好的性能

使用:
// 之前
const theme = useContext(ThemeContext);

// 现在
const theme = use(ThemeContext);

优势:
- 可以条件使用
- 更灵活

76. 如何迁移到React 19?

答案:
迁移步骤:
1. 升级依赖
2. 移除forwardRef
3. 更新ref usage
4. 测试应用

注意事项:
- 检查breaking changes
- 更新第三方库
- 渐进式迁移

77. React 19性能提升有哪些?

答案:
性能提升:
1. 自动优化(Compiler)
2. 更好的并发
3. 更少的JavaScript
4. 更快的hydration

测试结果:
- bundle大小减少30%
- 首屏速度提升40%
- 交互响应更快

78. TypeScript支持有什么改进?

答案:
改进:
1. 更好的类型推导
2. ref类型简化
3. 泛型组件支持
4. Actions类型

示例:
function Input({ ref }: { ref: Ref<HTMLInputElement> }) {
  return <input ref={ref} />;
}

79. 测试React 19组件注意什么?

答案:
注意事项:
1. 测试Server Components
2. 测试use() Hook
3. 测试Actions
4. 测试并发特性

工具:
- @testing-library/react v15+
- jest
- vitest

80. React 19最佳实践?

答案:
最佳实践:
1. 使用Server Components
2. 利用Compiler自动优化
3. 使用Actions简化表单
4. 用use()统一异步
5. 预加载关键资源

避免:
- 过度使用memo
- 手动优化(交给Compiler)
- 混用RSC和Client

状态管理 (81-100题)

81. Redux的工作流程?

答案:
流程:
1. 组件dispatch action
2. action通过middleware
3. reducer处理action
4. 生成新state
5. 通知订阅者
6. 组件re-render

三大原则:
- 单一数据源
- State只读
- 纯函数修改

82. Context和Redux的区别?

答案:
Context:
- React内置
- 简单易用
- 性能优化需手动
- 适合简单状态

Redux:
- 独立库
- 可预测性强
- 中间件支持
- 时间旅行调试
- 适合复杂应用

83. Zustand的优势?

答案:
优势:
1. 轻量级(1KB)
2. 无样板代码
3. TypeScript友好
4. 无Context Provider
5. 支持middleware

使用:
const useStore = create((set) => ({
  count: 0,
  increment: () => set(state => ({ count: state.count + 1 }))
}));

场景:
- 中小型项目
- 简单全局状态

84. Jotai和Recoil的区别?

答案:
Jotai:
- 更轻量
- API更简单
- 原子化
- 基于React Context

Recoil:
- Facebook开发
- 功能更全
- 异步支持好
- 更复杂

共同点:
- 原子化状态
- 细粒度更新
- 减少重渲染

85. Redux Toolkit的优势?

答案:
优势:
1. 简化Redux配置
2. 内置Immer
3. RTK Query
4. 自动生成actions
5. 最佳实践

使用:
const counterSlice = createSlice({
  name: 'counter',
  initialState: { value: 0 },
  reducers: {
    increment: state => {
      state.value += 1; // Immer自动处理
    }
  }
});

86. RTK Query vs React Query?

答案:
RTK Query:
- 集成Redux
- 类型安全
- 强制规范

React Query:
- 独立库
- 更灵活
- 生态更好
- 社区更大

选择:
- 已用Redux -> RTK Query
- 新项目 -> React Query

87. React Query的核心概念?

答案:
核心概念:
1. Queries: 数据获取
2. Mutations: 数据变更
3. Cache: 自动缓存
4. Refetch: 自动重新获取
5. Optimistic Updates: 乐观更新

使用:
const { data, isLoading } = useQuery({
  queryKey: ['todos'],
  queryFn: fetchTodos
});

优势:
- 自动缓存
- 后台刷新
- 重试机制

88. SWR的特点?

答案:
特点:
1. stale-while-revalidate策略
2. 轻量级
3. 自动重新验证
4. 预加载
5. 乐观更新

使用:
const { data, error } = useSWR('/api/user', fetcher);

对比React Query:
- 更轻量
- API更简单
- 功能较少

89. 状态管理库如何选择?

答案:
选择标准:
1. 项目规模
2. 团队熟悉度
3. 性能要求
4. TypeScript支持
5. 学习成本

推荐:
小型: Context + useState
中型: Zustand/Jotai + React Query
大型: Redux Toolkit + RTK Query
特殊: XState(状态机)

90. 如何实现全局状态?

javascript
// 使用Zustand
import create from 'zustand';

const useGlobalStore = create((set) => ({
  user: null,
  theme: 'light',
  setUser: (user) => set({ user }),
  setTheme: (theme) => set({ theme })
}));

// 使用
function App() {
  const { user, theme, setTheme } = useGlobalStore();
  return <div>{theme}</div>;
}

91. 如何实现状态持久化?

javascript
import create from 'zustand';
import { persist } from 'zustand/middleware';

const useStore = create(
  persist(
    (set) => ({
      user: null,
      setUser: (user) => set({ user })
    }),
    {
      name: 'user-storage',
      storage: localStorage
    }
  )
);

92. 如何处理异步状态?

javascript
// 使用React Query
const { data, isLoading, error } = useQuery({
  queryKey: ['user', id],
  queryFn: () => fetchUser(id)
});

if (isLoading) return <Loading />;
if (error) return <Error />;
return <User data={data} />;

93. 如何实现乐观更新?

javascript
const mutation = useMutation({
  mutationFn: updateTodo,
  onMutate: async (newTodo) => {
    // 取消查询
    await queryClient.cancelQueries({ queryKey: ['todos'] });
    
    // 保存快照
    const previousTodos = queryClient.getQueryData(['todos']);
    
    // 乐观更新
    queryClient.setQueryData(['todos'], old => [...old, newTodo]);
    
    return { previousTodos };
  },
  onError: (err, newTodo, context) => {
    // 回滚
    queryClient.setQueryData(['todos'], context.previousTodos);
  }
});

94. 如何实现无限滚动?

javascript
const {
  data,
  fetchNextPage,
  hasNextPage,
  isFetchingNextPage
} = useInfiniteQuery({
  queryKey: ['projects'],
  queryFn: ({ pageParam = 0 }) => fetchProjects(pageParam),
  getNextPageParam: (lastPage) => lastPage.nextCursor
});

// 监听滚动
const { ref } = useInView({
  onChange: (inView) => {
    if (inView && hasNextPage) {
      fetchNextPage();
    }
  }
});

95. 如何处理状态竞态?

javascript
function SearchComponent() {
  const [query, setQuery] = useState('');
  
  const { data } = useQuery({
    queryKey: ['search', query],
    queryFn: () => searchAPI(query),
    enabled: query.length > 0,
    // 自动取消旧请求
    keepPreviousData: true
  });
  
  return (
    <div>
      <input value={query} onChange={e => setQuery(e.target.value)} />
      {data?.results.map(item => <div key={item.id}>{item.name}</div>)}
    </div>
  );
}

96. 如何实现状态派生?

javascript
// 使用Zustand
const useStore = create((set, get) => ({
  items: [],
  get totalPrice() {
    return get().items.reduce((sum, item) => sum + item.price, 0);
  },
  get itemCount() {
    return get().items.length;
  }
}));

// 使用Recoil
const itemsState = atom({
  key: 'items',
  default: []
});

const totalPriceState = selector({
  key: 'totalPrice',
  get: ({ get }) => {
    const items = get(itemsState);
    return items.reduce((sum, item) => sum + item.price, 0);
  }
});

97. 如何处理表单状态?

javascript
// 使用React Hook Form
import { useForm } from 'react-hook-form';

function Form() {
  const { register, handleSubmit, formState: { errors } } = useForm();
  
  const onSubmit = (data) => {
    console.log(data);
  };
  
  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input {...register('username', { required: true })} />
      {errors.username && <span>必填</span>}
      
      <button type="submit">提交</button>
    </form>
  );
}

98. 如何实现状态同步?

javascript
// 多Tab同步
const useStore = create(
  persist(
    (set) => ({
      count: 0,
      increment: () => set(state => ({ count: state.count + 1 }))
    }),
    {
      name: 'count-storage',
      onRehydrateStorage: () => (state) => {
        // 监听storage变化
        window.addEventListener('storage', (e) => {
          if (e.key === 'count-storage') {
            // 同步状态
          }
        });
      }
    }
  )
);

99. 如何测试状态管理?

javascript
// 测试Zustand Store
import { renderHook, act } from '@testing-library/react';
import { useStore } from './store';

describe('Store', () => {
  it('should increment', () => {
    const { result } = renderHook(() => useStore());
    
    act(() => {
      result.current.increment();
    });
    
    expect(result.current.count).toBe(1);
  });
});

// 测试React Query
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';

const queryClient = new QueryClient();

const wrapper = ({ children }) => (
  <QueryClientProvider client={queryClient}>
    {children}
  </QueryClientProvider>
);

it('should fetch data', async () => {
  const { result } = renderHook(() => useUsers(), { wrapper });
  await waitFor(() => expect(result.current.isSuccess).toBe(true));
  expect(result.current.data).toBeDefined();
});

100. 面试总结和建议

答案:
准备建议:
1. 掌握核心原理
2. 熟悉常用Hooks
3. 了解性能优化
4. 实践项目经验
5. 关注最新特性
6. 练习手写代码

面试技巧:
1. 理解题意
2. 分析思路
3. 清晰表达
4. 编码规范
5. 考虑边界
6. 优化改进

总结

100道React面试题涵盖:

  1. 基础概念: JSX、组件、Props/State
  2. Hooks: useState、useEffect、useMemo等
  3. 性能优化: memo、虚拟滚动、代码分割
  4. React 19: 新特性和变化
  5. 状态管理: Redux、Context、Zustand
  6. 实战经验: 项目架构、问题解决

全面掌握这些题目可以应对大部分React面试。