互联网大厂200道高频React面试题

文章目录

React篇

1. React 的核心理念是什么?

答案解析
React 的核心理念是声明式编程和组件化开发。

  • 声明式:开发者只需描述 UI 的状态,React 负责将其高效渲染到 DOM。
  • 组件化:将 UI 拆分为独立、可复用的组件,提升代码可维护性。
  • 虚拟 DOM:通过内存中的轻量表示优化更新效率。

代码示例

function Button({ text }) {
  return <button>{text}</button>;
}

解析

  • 高效性:虚拟 DOM 和 diff 算法减少直接操作真实 DOM 的开销。
  • 对比命令式:如 jQuery 需手动操作 DOM,React 更简洁。

应用场景:构建复杂、可复用的 UI 组件。


2. React 的虚拟 DOM 是什么?如何提升性能?

答案解析
虚拟 DOM 是真实 DOM 的内存表示,React 通过它优化更新。

  • 工作原理:状态变化时生成新虚拟 DOM,与旧版本对比(diff),仅更新差异部分。
  • 性能提升:批量更新、减少直接 DOM 操作。

代码示例

function App() {
  const [count, setCount] = React.useState(0);
  return <div>{count}<button onClick={() => setCount(count + 1)}>Add</button></div>;
}

解析

  • diff 算法:同层比较,复用节点。
  • 优化key 属性加速列表 diff。

应用场景:动态列表、大型表单。


3. React 的 useState 和类组件的 setState 有什么区别?

答案解析

  • useState:函数组件的 Hook,返回状态和更新函数,更新是替换式。
  • setState:类组件方法,合并状态,支持回调。

代码示例

// useState
function Counter() {
  const [count, setCount] = React.useState(0);
  setCount(count + 1); // 替换
}

// setState
class Counter extends React.Component {
  state = { count: 0 };
  handleClick = () => {
    this.setState({ count: this.state.count + 1 }, () => console.log("Updated"));
  };
}

解析

  • 合并setState 合并对象,useState 需手动合并。
  • 回调setState 支持更新后回调,useStateuseEffect

应用场景useState 适合函数组件,setState 用于旧代码迁移。


4. React 的 useEffect 如何替代生命周期方法?

答案解析
useEffect 统一处理副作用,替代类组件的生命周期。

  • 挂载:空依赖数组模拟 componentDidMount
  • 更新:依赖变化模拟 componentDidUpdate
  • 卸载:返回清理函数模拟 componentWillUnmount

代码示例

function Example() {
  const [data, setData] = React.useState(null);

  React.useEffect(() => {
    fetchData().then(setData); // 挂载
    return () => console.log("Cleanup"); // 卸载
  }, []); // 空依赖

  React.useEffect(() => {
    console.log("Data updated:", data); // 更新
  }, [data]);

  return <div>{data}</div>;
}

解析

  • 灵活性:按依赖粒度控制执行。
  • 注意:避免无限循环,谨慎选择依赖。

应用场景:数据获取、事件监听。


5. React 的 useReducer 有什么优势?

答案解析
useReducer 管理复杂状态逻辑,替代 useState

  • 优势:集中式状态更新,类似 Redux 的 reducer 模式。

代码示例

const initialState = { count: 0 };
function reducer(state, action) {
  switch (action.type) {
    case "increment": return { count: state.count + 1 };
    default: return state;
  }
}

function Counter() {
  const [state, dispatch] = React.useReducer(reducer, initialState);
  return <button onClick={() => dispatch({ type: "increment" })}>{state.count}</button>;
}

解析

  • 对比 useState:更适合多状态联动。
  • 可预测性:状态变化逻辑清晰。

应用场景:表单管理、复杂计数器。


6. React 的 memo 如何优化性能?

答案解析
React.memo 是高阶组件,缓存组件渲染,防止不必要更新。

  • 原理:浅比较 props,props 不变则跳过渲染。

代码示例

const Child = React.memo(({ value }) => {
  console.log("Child rendered");
  return <div>{value}</div>;
});

function Parent() {
  const [count, setCount] = React.useState(0);
  return (
    <>
      <Child value="static" />
      <button onClick={() => setCount(count + 1)}>{count}</button>
    </>
  );
}

解析

  • 优化:避免父组件更新导致子组件重渲染。
  • 限制:仅浅比较,深层对象需自定义比较。

应用场景:静态子组件、列表项。


7. React 的 useCallbackuseMemo 有什么区别?

答案解析

  • useCallback:缓存函数,防止重复创建。
  • useMemo:缓存值,优化计算结果。

代码示例

function Example() {
  const [count, setCount] = React.useState(0);

  const increment = React.useCallback(() => setCount(count + 1), [count]);
  const doubled = React.useMemo(() => count * 2, [count]);

  return <button onClick={increment}>{doubled}</button>;
}

解析

  • useCallback:返回函数引用。
  • useMemo:返回计算值。
  • 性能:减少子组件重复渲染或昂贵计算。

应用场景:事件处理、计算属性。


8. React 的 Context 如何实现状态共享?

答案解析
Context 提供跨组件层级的数据传递,避免 props 逐层透传。

  • 步骤:创建 Context、Provider 提供值、Consumer 或 useContext 消费。

代码示例

const ThemeContext = React.createContext("light");

function App() {
  return (
    <ThemeContext.Provider value="dark">
      <Child />
    </ThemeContext.Provider>
  );
}

function Child() {
  const theme = React.useContext(ThemeContext);
  return <div>Theme: {theme}</div>;
}

解析

  • 性能:Provider 更新时所有消费者重渲染。
  • 优化:结合 useMemo 减少重复。

应用场景:主题切换、用户信息。


9. React 的 forwardRef 有什么作用?

答案解析
forwardRef 将 ref 转发到子组件,允许父组件访问子组件的 DOM 或实例。

  • 作用:解决函数组件无法直接绑定 ref 的问题。

代码示例

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

function Parent() {
  const inputRef = React.useRef();
  const focus = () => inputRef.current.focus();
  return (
    <>
      <Input ref={inputRef} />
      <button onClick={focus}>Focus</button>
    </>
  );
}

解析

  • 原理:ref 作为第二个参数传递。
  • 搭配:常与 useImperativeHandle 使用。

应用场景:表单聚焦、动画控制。


10. React 的 useImperativeHandle 如何自定义暴露接口?

答案解析
useImperativeHandle 配合 forwardRef,自定义暴露给父组件的 ref 接口。

  • 作用:限制暴露内容,增强封装性。

代码示例

const Input = React.forwardRef((props, ref) => {
  const inputRef = React.useRef();
  React.useImperativeHandle(ref, () => ({
    focus: () => inputRef.current.focus(),
  }));
  return <input ref={inputRef} />;
});

function Parent() {
  const ref = React.useRef();
  return (
    <>
      <Input ref={ref} />
      <button onClick={() => ref.current.focus()}>Focus</button>
    </>
  );
}

解析

  • 控制:仅暴露 focus,隐藏 DOM。
  • 安全性:防止直接操作内部。

应用场景:封装组件接口。


11. React 的渲染流程是怎样的?

答案解析
React 的渲染流程分为三个阶段:

  1. 触发更新:状态或 props 变化。
  2. 调和(Reconciliation):生成新虚拟 DOM,diff 对比。
  3. 提交(Commit):更新真实 DOM。

代码示例

function App() {
  const [count, setCount] = React.useState(0);
  return <button onClick={() => setCount(count + 1)}>{count}</button>;
}

解析

  • Fiber:React 16+ 使用 Fiber 架构,支持中断和优先级。
  • 批量更新:事件中多次 setState 合并。

应用场景:理解性能瓶颈。


12. React 的 key 属性有什么作用?

答案解析
key 是 React diff 算法的标识,帮助高效更新列表。

  • 作用:标记元素身份,减少重复渲染。

代码示例

function List() {
  const items = ["A", "B", "C"];
  return (
    <ul>
      {items.map(item => <li key={item}>{item}</li>)}
    </ul>
  );
}

解析

  • 错误用法:用索引作为 key,可能导致状态混乱。
  • 优化:使用唯一 ID。
  • 效果:提升列表增删性能。

应用场景:动态列表、表格。


13. React 的 setState 是同步还是异步?

答案解析
setState 在 React 事件中是异步的,在原生事件或 setTimeout 中是同步的。

  • 原因:React 批量更新优化性能。

代码示例

class App extends React.Component {
  state = { count: 0 };
  handleClick = () => {
    this.setState({ count: this.state.count + 1 });
    console.log(this.state.count); // 旧值
    setTimeout(() => this.setState({ count: this.state.count + 1 }), 0);
  };
  render() {
    return <button onClick={this.handleClick}>{this.state.count}</button>;
  }
}

解析

  • 异步:React 控制的事件。
  • 同步:非 React 控制上下文。
  • 解决:使用回调或 useEffect

应用场景:状态更新调试。


14. React 的 useEffect 如何避免无限循环?

答案解析
useEffect 无限循环通常因依赖项变化触发,需正确管理依赖数组。

  • 方法:确保依赖稳定,避免直接修改。

代码示例

function Example() {
  const [count, setCount] = React.useState(0);
  
  React.useEffect(() => {
    setCount(count + 1); // 错误:无限循环
  }, [count]);

  // 正确
  React.useEffect(() => {
    console.log("Mounted");
  }, []);
}

解析

  • 问题:依赖项频繁变化。
  • 解决:空数组或稳定引用(如 useCallback)。
  • 工具:ESLint react-hooks/exhaustive-deps

应用场景:副作用管理。


15. React 的 Hooks 和类组件相比有什么优势?

答案解析
Hooks 提供函数式编程范式,优于类组件:

  1. 复用性:逻辑可抽取为自定义 Hook。
  2. 简洁性:无 this 绑定,代码更清晰。
  3. 状态管理:更细粒度控制。

代码示例

function useCounter() {
  const [count, setCount] = React.useState(0);
  return { count, increment: () => setCount(count + 1) };
}

function App() {
  const { count, increment } = useCounter();
  return <button onClick={increment}>{count}</button>;
}

解析

  • 类组件:生命周期分散,复用困难。
  • Hooks:集中逻辑,易测试。

应用场景:现代 React 开发。


16. React 的 useRef 有哪些用途?

答案解析
useRef 创建持久化引用,主要用途:

  1. 访问 DOM:绑定到元素获取实例。
  2. 保存变量:跨渲染保持值不变。

代码示例

function Input() {
  const inputRef = React.useRef(null);
  const countRef = React.useRef(0);

  const focus = () => inputRef.current.focus();
  const increment = () => countRef.current++;

  return (
    <>
      <input ref={inputRef} />
      <button onClick={focus}>Focus</button>
      <button onClick={increment}>Count: {countRef.current}</button>
    </>
  );
}

解析

  • 不变性:不触发重渲染。
  • 替代:替代类组件的实例变量。

应用场景:表单控制、计数器。


17. React 的 lazySuspense 如何实现懒加载?

答案解析
React.lazy 动态加载组件,Suspense 提供加载中状态。

  • 作用:减少首屏加载体积。

代码示例

const LazyComponent = React.lazy(() => import("./LazyComponent"));

function App() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <LazyComponent />
    </Suspense>
  );
}

解析

  • 原理import() 返回 Promise。
  • 构建:Webpack 分割代码块。
  • 注意:SSR 需特殊处理。

应用场景:路由组件、弹窗。


18. React 的 useContext 如何优化性能?

答案解析
useContext 使用不当可能导致不必要重渲染,优化方法:

  1. 拆分 Context:细化数据范围。
  2. 结合 useMemo:缓存值。

代码示例

const CountContext = React.createContext();

function Provider() {
  const [count, setCount] = React.useState(0);
  const value = React.useMemo(() => ({ count, setCount }), [count]);
  return (
    <CountContext.Provider value={value}>
      <Consumer />
    </CountContext.Provider>
  );
}

function Consumer() {
  const { count } = React.useContext(CountContext);
  return <div>{count}</div>;
}

解析

  • 问题:Provider 更新影响所有消费者。
  • 优化:稳定引用减少渲染。

应用场景:全局状态优化。


19. React 的 useEffect 如何处理异步操作?

答案解析
useEffect 不直接支持 async,但可包裹异步函数。

  • 方法:在 effect 中调用 async 函数。

代码示例

function DataFetcher() {
  const [data, setData] = React.useState(null);

  React.useEffect(() => {
    const fetchData = async () => {
      const result = await apiCall();
      setData(result);
    };
    fetchData();
  }, []);

  return <div>{data}</div>;
}

解析

  • 清理:返回函数处理取消。
  • 注意:避免直接 async () => 作为 effect。
  • 替代useAsync 自定义 Hook。

应用场景:API 数据加载。


20. React 的 Fragment 有什么作用?

答案解析
Fragment 允许返回多个子节点,无需额外包裹元素。

  • 作用:减少 DOM 层级,优化结构。

代码示例

function List() {
  return (
    <React.Fragment>
      <li>Item 1</li>
      <li>Item 2</li>
    </React.Fragment>
  );
  // 简写: <>...</>
}

解析

  • 替代:替代无意义的 <div>
  • key:支持 key 属性(如列表)。
  • 性能:减少 DOM 操作。

应用场景:列表渲染、条件组。


21. React 的 useLayoutEffectuseEffect 有什么区别?

答案解析

  • useEffect:异步执行,DOM 更新后运行。
  • useLayoutEffect:同步执行,DOM 更新前运行。

代码示例

function Example() {
  const [width, setWidth] = React.useState(0);
  const ref = React.useRef();

  React.useLayoutEffect(() => {
    setWidth(ref.current.offsetWidth); // 同步获取
  }, []);

  return <div ref={ref}>Width: {width}</div>;
}

解析

  • 时机useLayoutEffect 避免闪烁。
  • 性能useEffect 不阻塞渲染。
  • 选择:布局相关用前者。

应用场景:测量 DOM、动画。


22. React 的 useTransition 如何优化交互?

答案解析
useTransition(React 18+)标记非紧急更新,优化用户体验。

  • 作用:区分紧急和过渡状态更新。

代码示例

function Search() {
  const [query, setQuery] = React.useState("");
  const [results, setResults] = React.useState([]);
  const [isPending, startTransition] = React.useTransition();

  const handleChange = (e) => {
    setQuery(e.target.value);
    startTransition(() => {
      setResults(search(e.target.value)); // 延迟更新
    });
  };

  return (
    <>
      <input value={query} onChange={handleChange} />
      {isPending ? "Loading..." : results.map(r => <div>{r}</div>)}
    </>
  );
}

解析

  • 效果:输入流畅,搜索延迟。
  • Fiber:基于并发渲染。
  • 用途:提升响应性。

应用场景:搜索、过滤。


23. React 的 useDeferredValue 有什么作用?

答案解析
useDeferredValue(React 18+)延迟值的更新,优化复杂渲染。

  • 作用:让低优先级任务延迟执行。

代码示例

function List({ input }) {
  const deferredInput = React.useDeferredValue(input);
  const items = React.useMemo(() => heavyCompute(deferredInput), [deferredInput]);
  return <ul>{items.map(i => <li>{i}</li>)}</ul>;
}

function App() {
  const [input, setInput] = React.useState("");
  return (
    <>
      <input value={input} onChange={e => setInput(e.target.value)} />
      <List input={input} />
    </>
  );
}

解析

  • 效果:输入不卡顿,列表稍后更新。
  • 对比 useTransition:更简单,无需显式标记。
  • 场景:大数据渲染。

应用场景:实时输入优化。


24. React 的 StrictMode 有什么作用?

答案解析
StrictMode 是开发工具,检测潜在问题。

  • 功能
    1. 检查不安全的生命周期。
    2. 警告副作用问题。
    3. 双次调用 Hooks(React 18)。

代码示例

function App() {
  return (
    <React.StrictMode>
      <Child />
    </React.StrictMode>
  );
}

function Child() {
  React.useEffect(() => console.log("Effect")); // 打印两次
  return <div>Child</div>;
}

解析

  • 目的:暴露 bug,不影响生产。
  • 双次调用:模拟卸载后重载。
  • 注意:仅开发环境生效。

应用场景:代码健壮性检查。


25. React 的 createPortal 如何实现弹窗?

答案解析
createPortal 将组件渲染到指定 DOM 节点,脱离父组件层级。

  • 作用:解决层级和样式冲突。

代码示例

function Modal({ children }) {
  return ReactDOM.createPortal(
    <div className="modal">{children}</div>,
    document.getElementById("modal-root")
  );
}

function App() {
  return (
    <>
      <Modal>Modal Content</Modal>
      <div id="modal-root" />
    </>
  );
}

解析

  • 对比 Teleport:Vue 3 内置,React 需手动。
  • 优势:保持事件冒泡。
  • 用途:全局组件渲染。

应用场景:弹窗、tooltip。


26. React 的组件设计原则有哪些?

答案解析
React 组件设计遵循以下原则:

  1. 单一职责:每个组件专注单一功能。
  2. 可复用性:抽象通用逻辑,减少重复。
  3. 可组合性:通过 props 和 children 组合组件。
  4. 状态隔离:状态尽量局部化,避免全局依赖。

代码示例

function Button({ onClick, children }) {
  return <button onClick={onClick}>{children}</button>;
}

function App() {
  return (
    <Button onClick={() => alert("Clicked")}>Click Me</Button>
  );
}

解析

  • 单一职责Button 只负责渲染和点击。
  • 可复用性:通过 children 定制内容。
  • 优化:避免深层嵌套,保持扁平结构。

应用场景:UI 库开发、复杂页面。


27. React 的 useCallback 如何优化子组件渲染?

答案解析
useCallback 缓存函数引用,防止子组件因函数重新创建而重渲染。

  • 作用:稳定 props 中的回调函数。

代码示例

const Child = React.memo(({ onChange }) => {
  console.log("Child rendered");
  return <input onChange={onChange} />;
});

function Parent() {
  const [value, setValue] = React.useState("");
  const handleChange = React.useCallback(e => setValue(e.target.value), []);
  return <Child onChange={handleChange} />;
}

解析

  • 问题:未缓存的函数每次渲染都不同。
  • 解决useCallback 确保引用一致。
  • 依赖:空数组表示不变,需谨慎选择。

应用场景:表单输入、事件处理。


28. React 的 useMemo 如何优化昂贵计算?

答案解析
useMemo 缓存计算结果,仅在依赖变化时重新计算。

  • 作用:避免重复执行性能开销大的操作。

代码示例

function ExpensiveList({ items }) {
  const filtered = React.useMemo(() => {
    return items.filter(item => item > 0);
  }, [items]);
  return <ul>{filtered.map(i => <li>{i}</li>)}</ul>;
}

function App() {
  const [items, setItems] = React.useState([1, -1, 2]);
  return <ExpensiveList items={items} />;
}

解析

  • 性能:减少不必要过滤。
  • 依赖:确保 items 变化时更新。
  • 对比 useCallback:返回值的缓存。

应用场景:大数据过滤、复杂计算。


29. React 的自定义 Hook 如何设计?

答案解析
自定义 Hook 封装可复用逻辑,遵循命名(useXxx)和 Hooks 规则。

  • 原则
    1. 逻辑复用。
    2. 独立性。
    3. 参数化配置。

代码示例

function useToggle(initialValue = false) {
  const [value, setValue] = React.useState(initialValue);
  const toggle = () => setValue(prev => !prev);
  return [value, toggle];
}

function App() {
  const [isOn, toggle] = useToggle();
  return <button onClick={toggle}>{isOn ? "ON" : "OFF"}</button>;
}

解析

  • 复用:多个组件共享切换逻辑。
  • 灵活性:支持初始值参数。
  • 规则:内部只能调用其他 Hooks。

应用场景:状态管理、工具函数。


30. React 的 useReducer 如何与 Context 结合?

答案解析
useReducer 和 Context 结合,实现类似 Redux 的全局状态管理。

  • 步骤:Context 传递状态和 dispatch,useReducer 更新逻辑。

代码示例

const CountContext = React.createContext();

function reducer(state, action) {
  switch (action.type) {
    case "increment": return { count: state.count + 1 };
    default: return state;
  }
}

function Provider({ children }) {
  const [state, dispatch] = React.useReducer(reducer, { count: 0 });
  return (
    <CountContext.Provider value={
  
  { state, dispatch }}>
      {children}
    </CountContext.Provider>
  );
}

function Counter() {
  const { state, dispatch } = React.useContext(CountContext);
  return (
    <button onClick={() => dispatch({ type: "increment" })}>
      {state.count}
    </button>
  );
}

function App() {
  return (
    <Provider>
      <Counter />
    </Provider>
  );
}

解析

  • 优势:集中状态管理,减少 prop drilling。
  • 优化:用 useMemo 稳定 value。

应用场景:小型应用全局状态。


31. React 的 useEffect 如何处理事件监听?

答案解析
useEffect 通过添加和清理事件监听器,管理副作用。

  • 方法:监听器在挂载时绑定,卸载时移除。

代码示例

function WindowSize() {
  const [size, setSize] = React.useState(window.innerWidth);

  React.useEffect(() => {
    const handleResize = () => setSize(window.innerWidth);
    window.addEventListener("resize", handleResize);
    return () => window.removeEventListener("resize", handleResize);
  }, []);

  return <div>Width: {size}px</div>;
}

解析

  • 清理:防止内存泄漏。
  • 依赖:空数组确保只绑定一次。
  • 注意:动态事件需更新依赖。

应用场景:窗口大小、滚动监听。


32. React 的 memo 如何自定义比较逻辑?

答案解析
React.memo 支持第二个参数,自定义 props 比较逻辑。

  • 作用:替代默认浅比较,处理深层对象。

代码示例

const Child = React.memo(({ data }) => (
  <div>{data.name}</div>
), (prevProps, nextProps) => {
  return prevProps.data.name === nextProps.data.name;
});

function Parent() {
  const [state, setState] = React.useState({ name: "Alice", age: 25 });
  return <Child data={state} />;
}

解析

  • 默认:浅比较只检查引用。
  • 自定义:精确控制更新条件。
  • 性能:避免复杂比较函数。

应用场景:嵌套对象 props。


33. React 的 useRef 如何保存上一次状态?

答案解析
useRef 保存跨渲染的值,可记录上一次状态。

  • 作用:不触发重渲染,追踪历史值。

代码示例

function Counter() {
  const [count, setCount] = React.useState(0);
  const prevCountRef = React.useRef();

  React.useEffect(() => {
    prevCountRef.current = count;
  }, [count]);

  return (
    <div>
      <p>Current: {count}, Previous: {prevCountRef.current}</p>
      <button onClick={() => setCount(count + 1)}>Add</button>
    </div>
  );
}

解析

  • 原理useRef 持久化存储。
  • 替代:类组件的实例变量。
  • 注意:初始值为 undefined

应用场景:状态变化对比。


34. React 的 useLayoutEffect 如何避免闪烁?

答案解析
useLayoutEffect 在 DOM 更新前同步执行,避免视觉不一致。

  • 作用:处理布局相关副作用。

代码示例

function Position() {
  const [pos, setPos] = React.useState(0);
  const ref = React.useRef();

  React.useLayoutEffect(() => {
    const rect = ref.current.getBoundingClientRect();
    setPos(rect.top); // 同步更新
  }, []);

  return <div ref={ref}>Top: {pos}px</div>;
}

解析

  • 对比 useEffect:后者异步可能闪烁。
  • 性能:阻塞渲染,谨慎使用。
  • 场景:需要立即测量 DOM。

应用场景:动画初始化、布局计算。


35. React 的 useTransition 如何优化大数据渲染?

答案解析
useTransition(React 18+)将大数据渲染标记为过渡任务,优先响应用户交互。

  • 作用:避免阻塞 UI 线程。

code示例

function FilterList() {
  const [input, setInput] = React.useState("");
  const [list, setList] = React.useState([]);
  const [isPending, startTransition] = React.useTransition();

  const handleChange = (e) => {
    setInput(e.target.value);
    startTransition(() => {
      setList(filterLargeData(e.target.value));
    });
  };

  return (
    <>
      <input value={input} onChange={handleChange} />
      {isPending ? "Loading..." : list.map(i => <div>{i}</div>)}
    </>
  );
}

解析

  • 效果:输入流畅,列表稍后更新。
  • 并发:基于 Fiber 优先级调度。
  • 注意:需合理提示加载。

应用场景:实时搜索、大列表。


36. React 的 useDeferredValue 如何与输入框结合?

答案解析
useDeferredValue 延迟输入值更新,优化复杂渲染响应。

  • 作用:保持输入流畅,延迟副作用。

code示例

function Search() {
  const [query, setQuery] = React.useState("");
  const deferredQuery = React.useDeferredValue(query);
  const results = React.useMemo(() => search(deferredQuery), [deferredQuery]);

  return (
    <>
      <input value={query} onChange={e => setQuery(e.target.value)} />
      <div>{results}</div>
    </>
  );
}

解析

  • 效果:输入不卡顿,搜索稍后执行。
  • 对比 debounce:React 内部管理。
  • 用途:提升用户体验。

应用场景:动态搜索、下拉建议。


37. React 的 Context 如何避免不必要重渲染?

答案解析
Context 的 Provider 更新会导致所有消费者重渲染,优化方法:

  1. 拆分 Context:隔离变化部分。
  2. useMemo:稳定 value。

code示例

const CountContext = React.createContext();

function Provider() {
  const [count, setCount] = React.useState(0);
  const value = React.useMemo(() => ({ count }), [count]);
  return (
    <CountContext.Provider value={value}>
      <Consumer />
      <button onClick={() => setCount(count + 1)}>Add</button>
    </CountContext.Provider>
  );
}

const Consumer = React.memo(() => {
  const { count } = React.useContext(CountContext);
  return <div>{count}</div>;
});

解析

  • 问题value 引用变化触发渲染。
  • 解决:缓存对象或细化 Context。
  • 替代:Redux 或状态提升。

应用场景:全局状态优化。


38. React 的 forwardRef 如何与 Hooks 结合?

答案解析
forwardRef 将 ref 传递给函数组件,结合 Hooks 实现动态控制。

  • 作用:暴露 DOM 或自定义方法。

code示例

const Input = React.forwardRef((props, ref) => {
  const inputRef = React.useRef();
  React.useImperativeHandle(ref, () => ({
    focus: () => inputRef.current.focus(),
    clear: () => inputRef.current.value = "",
  }));
  return <input ref={inputRef} {...props} />;
});

function App() {
  const ref = React.useRef();
  return (
    <>
      <Input ref={ref} />
      <button onClick={() => ref.current.clear()}>Clear</button>
    </>
  );
}

解析

  • 灵活性:自定义暴露接口。
  • HooksuseImperativeHandle 增强。
  • 用途:增强组件交互。

应用场景:表单管理、焦点控制。


39. React 的 useEffect 如何模拟类组件生命周期?

答案解析
useEffect 通过依赖数组和清理函数,模拟类组件生命周期:

  • componentDidMount:空依赖。
  • componentDidUpdate:指定依赖。
  • componentWillUnmount:返回清理。

code示例

function Component() {
  const [data, setData] = React.useState(null);

  React.useEffect(() => {
    console.log("Mounted"); // DidMount
    fetchData().then(setData);

    return () => console.log("Unmounted"); // WillUnmount
  }, []);

  React.useEffect(() => {
    console.log("Data updated:", data); // DidUpdate
  }, [data]);

  return <div>{data}</div>;
}

解析

  • 统一性:取代分散的生命周期。
  • 注意:依赖需完整声明。
  • 调试:避免遗漏清理。

应用场景:组件初始化、销毁。


40. React 的 useCallback 如何与 memo 协同?

答案解析
useCallback 稳定函数引用,与 memo 配合防止子组件重渲染。

  • 作用:优化性能,减少不必要更新。

code示例

const Child = React.memo(({ onClick }) => {
  console.log("Child rendered");
  return <button onClick={onClick}>Click</button>;
});

function Parent() {
  const [count, setCount] = React.useState(0);
  const handleClick = React.useCallback(() => console.log("Clicked"), []);
  return (
    <>
      <Child onClick={handleClick} />
      <button onClick={() => setCount(count + 1)}>{count}</button>
    </>
  );
}

解析

  • 协同memo 检查 props,useCallback 确保稳定。
  • 依赖:空数组表示不变。
  • 效果count 更新不影响 Child

应用场景:事件回调优化。


41. React 的 useReducer 如何处理复杂表单?

答案解析
useReducer 通过集中式 reducer 管理表单状态,提升可维护性。

  • 优势:状态更新逻辑清晰。

code示例

const initialState = { name: "", email: "" };
function reducer(state, action) {
  switch (action.type) {
    case "update": return { ...state, [action.field]: action.value };
    default: return state;
  }
}

function Form() {
  const [state, dispatch] = React.useReducer(reducer, initialState);
  return (
    <>
      <input
        value={state.name}
        onChange={e => dispatch({ type: "update", field: "name", value: e.target.value })}
      />
      <input
        value={state.email}
        onChange={e => dispatch({ type: "update", field: "email", value: e.target.value })}
      />
    </>
  );
}

解析

  • 集中:所有更新通过 dispatch
  • 扩展性:易添加校验、重置。
  • 对比 useState:多字段更简洁。

应用场景:多输入表单。


42. React 的 useMemo 如何优化列表渲染?

答案解析
useMemo 缓存列表数据或组件,减少重复计算和渲染。

  • 作用:提升大数据列表性能。

code示例

function List({ items }) {
  const renderedItems = React.useMemo(() => {
    return items.map(item => <li key={item.id}>{item.name}</li>);
  }, [items]);
  return <ul>{renderedItems}</ul>;
}

function App() {
  const [items, setItems] = React.useState([{ id: 1, name: "A" }]);
  return <List items={items} />;
}

解析

  • 优化items 不变时复用结果。
  • 注意:确保 key 唯一。
  • 搭配:结合 memo 更佳。

应用场景:动态列表、过滤结果。


43. React 的 useContext 如何与 Redux 对比?

答案解析
useContext 和 Redux 都用于状态管理,但适用场景不同:

  • useContext:轻量级,适合简单共享。
  • Redux:复杂应用,提供中间件和调试工具。

code示例(useContext)

const StateContext = React.createContext();
function App() {
  const [state, setState] = React.useState({ count: 0 });
  return (
    <StateContext.Provider value={
  
  { state, setState }}>
      <Child />
    </StateContext.Provider>
  );
}

解析

  • useContext:无额外依赖,易上手。
  • Redux:支持时间旅行、action 追踪。
  • 选择:小型用 Context,大型用 Redux。

应用场景:小型项目 vs 企业级应用。


44. React 的 useEffect 如何处理竞态条件?

答案解析
useEffect 中的异步操作可能导致竞态条件,需通过清理或标志解决。

  • 问题:多个请求顺序混乱。

code示例

function Fetcher({ id }) {
  const [data, setData] = React.useState(null);

  React.useEffect(() => {
    let isMounted = true;
    fetchData(id).then(result => {
      if (isMounted) setData(result);
    });
    return () => { isMounted = false; };
  }, [id]);

  return <div>{data}</div>;
}

解析

  • 清理:标志确保最新请求生效。
  • 替代:使用 AbortController 取消请求。
  • 效果:避免旧数据覆盖。

应用场景:动态 ID 数据加载。


45. React 的 lazy 如何与路由结合?

答案解析
React.lazy 结合路由实现按需加载,减少首屏体积。

  • 步骤:动态导入组件,搭配 Suspense

code示例

import { BrowserRouter, Route, Routes } from "react-router-dom";

const Home = React.lazy(() => import("./Home"));
const About = React.lazy(() => import("./About"));

function App() {
  return (
    <BrowserRouter>
      <Suspense fallback={<div>Loading...</div>}>
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/about" element={<About />} />
        </Routes>
      </Suspense>
    </BrowserRouter>
  );
}

解析

  • 效果:按路由分割代码。
  • 构建:Webpack 自动分包。
  • 注意:SSR 需额外配置。

应用场景:SPA 路由优化。


46. R
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天涯学馆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值