刷刷题48 (setState常规问答)

1. 为什么说setState是异步的?React如何处理多个setState调用?

  • 异步原因 ‌:为了优化性能,React会将多个setState合并为一次更新,减少不必要的渲染次数(批处理机制)。

  • 处理方式‌:

    kotlin 复制代码
    // 连续调用会被合并,最终count只+1
    this.setState({ count: this.state.count + 1 });
    this.setState({ count: this.state.count + 1 });

    React内部通过updater队列收集多个更新,在事件循环末尾统一处理。


2. 如何强制在setState后立即获取最新状态?

使用setState的‌回调函数 ‌或‌Promise封装‌:

javascript 复制代码
// 方式1:回调函数
this.setState({ count: 1 }, () => console.log(this.state.count));

// 方式2:async/await(需自行封装)
const setStateAsync = (state) => new Promise(resolve => this.setState(state, resolve));
await setStateAsync({ count: 1 });

3. 哪些场景下setState会同步执行?

在React的‌控制范围之外‌的代码中会同步更新:

  • setTimeout/setInterval
  • 原生DOM事件监听器
  • Promise回调
javascript 复制代码
setTimeout(() => {
  this.setState({ count: 1 }); // 同步更新
  console.log(this.state.count); // 输出1
}, 0);

4. setState(partialState, callback)this.state = ...直接修改的区别?

  • ‌**setState**‌:

    • 触发组件重新渲染
    • 遵守React的更新队列机制
    • 支持批处理优化
  • ‌**直接修改this.state**‌:

    • 不会触发渲染(状态不更新到UI)
    • 破坏React状态管理机制,导致数据不一致

5. 为什么说在setState中依赖this.state的值是危险的?如何解决?

  • 危险原因‌:异步更新可能导致获取的是过期状态

    kotlin 复制代码
    // ❌ 错误:可能基于旧值计算
    this.setState({ count: this.state.count + 1 });
  • 解决方案 ‌:使用‌函数式更新

    javascript 复制代码
    // ✅ 正确:接收前一个状态
    this.setState((prevState) => ({ count: prevState.count + 1 }));

6. React 18中setState的批处理机制有哪些改进?

  • React 17及之前‌:仅在React事件处理函数中自动批处理

  • React 18+ ‌:

    • 所有场景(包括Promise、setTimeout等)默认自动批处理
    • 可使用flushSync强制同步更新:
    javascript 复制代码
    import { flushSync } from 'react-dom';
    flushSync(() => this.setState({ count: 1 })); // 立即更新

7. 如何避免setState导致的不必要重复渲染?

  • 浅比较优化‌:

    scala 复制代码
    class Component extends React.PureComponent { // 自动浅比较props/state
      state = { list: [] };
      addItem = () => {
        // ✅ 正确:返回新数组
        this.setState(prev => ({ list: [...prev.list, newItem] }));
      }
    }
  • 手动控制‌:

    javascript 复制代码
    shouldComponentUpdate(nextProps, nextState) {
      return nextState.count !== this.state.count; // 仅当count变化时更新
    }

8. 在componentWillUpdate中调用setState会发生什么?

  • 引发无限循环 ‌:
    componentWillUpdatesetState → 重新渲染 → 再次触发componentWillUpdate
  • 解决方案 ‌:
    禁止在此生命周期中调用setState,改用componentDidUpdate处理副作用。

9. 为什么推荐在setState中返回不可变数据?如何正确实现?

  • 不可变性优势‌:

    • 便于React快速比较状态变化
    • 避免引用类型数据共享导致的副作用
  • 正确写法‌:

    kotlin 复制代码
    // ✅ 对象
    this.setState({ user: { ...this.state.user, name: 'Alice' } });
    
    // ✅ 数组
    this.setState({ list: [...this.state.list, newItem] });

10. setState在异步操作(如AJAX请求)中可能遇到什么问题?如何解决?

  • 竞态条件(Race Condition) ‌:

    当多个异步操作返回顺序不确定时,可能导致状态覆盖

  • 解决方案‌:

    1. 使用AbortController取消过期请求
    2. 函数式更新确保基于最新状态:
    ini 复制代码
    fetchData().then(data => {
      this.setState(prev => ({ 
        list: prev.filterId === currentId ? data : prev.list 
      }));
    });
相关推荐
加减法原则4 分钟前
Vue3 组合式函数:让你的代码复用如丝般顺滑
前端·vue.js
yanlele36 分钟前
我用爬虫抓取了 25 年 6 月掘金热门面试文章
前端·javascript·面试
lichenyang45341 分钟前
React移动端开发项目优化
前端·react.js·前端框架
天若有情67342 分钟前
React、Vue、Angular的性能优化与源码解析概述
vue.js·react.js·angular.js
你的人类朋友1 小时前
🍃Kubernetes(k8s)核心概念一览
前端·后端·自动化运维
web_Hsir1 小时前
vue3.2 前端动态分页算法
前端·算法
烛阴1 小时前
WebSocket实时通信入门到实践
前端·javascript
草巾冒小子1 小时前
vue3实战:.ts文件中的interface定义与抛出、其他文件的调用方式
前端·javascript·vue.js
追逐时光者2 小时前
面试第一步,先准备一份简洁、优雅的简历模板!
后端·面试
DoraBigHead2 小时前
你写前端按钮,他们扛服务器压力:搞懂后端那些“黑话”!
前端·javascript·架构