NervJS / nerv

A blazing fast React alternative, compatible with IE8 and React 16.
https://nerv.aotu.io
MIT License
5.42k stars 267 forks source link

setState的回调函数中再次setState,第二个setState回调函数无法及时获取设置后的值 #161

Open fjyhub opened 4 years ago

fjyhub commented 4 years ago

问题描述

setState的回调函数中再次setState,第二个setState回调函数中无法及时获取更改后的值

复现步骤

  1. state 中定义两个变量{page: 1, num: 1}
  2. 点击触发更改num值的方法 3.在setState回调方法中更改page值为2
  3. 此时回调函数中page值仍然为1,没有被改变
    state = {
      num: 1,
      page: 1
    }
    this.setState({num: 1},()=> {
        this.setState({page: 2}, ()=> {
          // 此时page值没被改变,返回结果为1
          console.log(this.state.page)
        })
    })

期望行为

返回正常更改后的值

系统信息

👽 Taro v2.0.4

Taro CLI 2.0.4 environment info: System: OS: macOS High Sierra 10.13.6 Shell: 3.2.57 - /bin/bash Binaries: Node: 12.13.0 - /usr/local/bin/node Yarn: 1.10.1 - /usr/local/bin/yarn npm: 6.12.0 - /usr/local/bin/npm

taro-bot[bot] commented 4 years ago

CC @Littly

taro-bot[bot] commented 4 years ago

欢迎提交 Issue~

如果你提交的是 bug 报告,请务必遵循 Issue 模板的规范,尽量用简洁的语言描述你的问题,最好能提供一个稳定简单的复现。🙏🙏🙏

如果你的信息提供过于模糊或不足,或者已经其他 issue 已经存在相关内容,你的 issue 有可能会被关闭。

Good luck and happy coding~

fjyhub commented 4 years ago

没人给解决方案么?这个是整个框架底层有问题

YunShengTeng commented 3 years ago

图1:实现代码image

图2:nervjs的setState源码 image

图3:nervjs的clearCallBacks源码 image

图4:chrome调用栈时间轴 image

当第一setState执行完,render执行完,开始清理第一个setState的callback,从_pendingCallbacks数组中弹出callback执行,也就是f1,执行f1,遇到了setState,把f2push进_pendingCallbacks,f1执行完,检查_pendingCallbacks数组,还有一个f2,于是弹出f2,执行f2,但是其实这时state并没有更新,但是打印出的内容还是上次的state,这种场景下和React输出是不一致的。

@fjyGitHub 我给出的方案: 1.不要这样写; 2.在第二个callback用setTimeout。