关于React项目的解决点

最近有这样一个需求,原本该页面部分数据是来自于location.state,现在想要通过url直接输入参数(例如id)从而与后端接口通过该id获取剩余的所需数据。

但是出现了一个问题,因为在componentDidMount这个生命周期中就需要使用从后端获取到的数据,原本设想是在componentDidMount中使用dispatch异步请求数据后,通过redux改变this.props后使用setstate赋值给this.state(一切为了规范!方便!)。

不幸的是,setState函数是一个异步的函数,而在componentDidMount中进行setstate将会让新设置的state的值在componentDIDMount中无法获取,具体原因如下:

componentDidMount钩子将会在组件挂载后及页面更新前发生,而当使用了setState意味着触发一次额外渲染,再走一次render,并且在页面更新前。

当使用了setState将发生以下事情:

  1. setState传入的partialState参数存储在当前组件实例的state暂存队列中。
  2. 判断当前React是否处于批量更新状态,如果是,将当前组件加入待更新的组件队列中。
  3. 如果未处于批量更新状态,将批量更新状态标识设置为true,用事务再次调用前一步方法,保证当前组件加入到了待更新组件队列中。
  4. 调用事务的waper方法,遍历待更新组件队列依次执行更新。
  5. 执行生命周期componentWillReceiveProps
  6. 将组件的state暂存队列中的state进行合并,获得最终要更新的state对象,并将队列置为空。
  7. 执行生命周期componentShouldUpdate,根据返回值判断是否要继续更新。
  8. 执行生命周期componentWillUpdate
  9. 执行真正的更新,render重新渲染。
  10. 执行生命周期componentDidUpdate

简单来说就是调用setstate后将新state存入缓存队列,判断状态变量isBatchingUpdates如果为true就存入缓存队列dirtyComponents,为false则执行更新。

综上所述,componentDidMount中其实处于首次渲染的事务当中,这次事务的渲染尚未完成,而首次渲染的时候会将isBatchingUpdates设置为true,这时我们在componentDidMount中调用setState,react会发现当前事务尚未完成,只会直接将修改后的state放入到dirtyComponents中,等待最终渲染周期完成时,将所有的state进行合并,一次性render。

function enqueueUpdate(component) {
  ensureInjected();
 
  //不在渲染周期中
  if (!batchingStrategy.isBatchingUpdates) {
    batchingStrategy.batchedUpdates(enqueueUpdate, component);
    return;
  }
 
//渲染周期中,直接缓存state等待下一步更新
  dirtyComponents.push(component);
}

所以当我想要在componentDidMount中使用state时还是init的值。

解决办法:将需要数据的操作放在setState函数的第二个参数中操作this.setState({},()=>{})(推荐)

使用settimeout或直接在constructor使用this.state

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值