This synthetic event is reused for performance reasons. If you're seeing ···

2,576 阅读3分钟

这咋了呢?

今天在学习React-redux的时候,在将一个大组件拆分成UI组件和容器组件之后,突然报了这个错误:

getInputChangeAction = (value) => ({
  type: 'change_input_value',
  value
})
handleInputChange(e) {
    const action = getInputChangeAction(e.target.value);
    store.dispatch(action);
}
handleStoreChange() {
    this.setState(store.getState());
}

This synthetic event is reused for performance reasons. If you're seeing this, you're accessing the property 'nativeEvent' on a released/nullified synthetic event. This is set to null. If you must keep the original synthetic event around, use event.persist().

  • SyntheticEvent 对象是通过合并得到的。 这意味着在事件回调被调用后,SyntheticEvent 对象将被重用并且所有属性都将被取消。这是出于性能原因。因此,您无法以异步方式访问该事件。

咋解决呢?

这说明我们正在使用的e.target处于异步操作中,查询文档发现,如果你想异步访问事件属性,你需在事件上调用event.persist(),此方法会从事件池中移除合成事件,允许用户代码保留对事件的引用。 姑且算是把警告消除了。

然鹅!这并不是一个合格的学习者的心态,我们需要刨根问底!

在使用某度搜索后,得知这样一个知识点:

Think of setState() as a request rather than an immediate command to update the component. For better perceived performance, React may delay it, and then update several components in a single pass. React does not guarantee that the state changes are applied immediately. setState() does not always immediately update the component. It may batch or defer the update until later.

  • setState当作是请求更新组件,而不是立即更新组件。为了性能,React会延迟更新,会把多个组件的更新放在一次操作里。React不保证state的改变会立刻发生。 setState并不总是立即更新组件。它可能会推后至批量更新。

那setStates什么时候是异步的呢?

React 文档给出这样的说法:

目前,在事件处理函数内部的setState是异步的

那这玩意儿咋理解呢?官方文档也给出了解释:

例如,如果ParentChild在同一个click事件中都调用了setState,这样就可以确保Child不会被重新渲染两次。取而代之的是,React会将该state冲洗到浏览器事件结束的时候,在统一地进行更新。这种机制可以在大型应用中得到很好的提升。

那这样就可以解释为什么我的代码会出问题了,实际上我进行UI组件和容器组件拆分后,UI组件作为容器组件的子组件,在进行redux工作流程后,统一进行了state的更新,即上面最后一个函数,这就导致了异步的出现。

那既然明白了这个道理,我们就需要做一个小处理就ok了,不要在setState的更新函数中访问event变量

修改后的代码如下:

getInputChangeAction = (value) => ({
  type: 'change_input_value',
  value
})
handleInputChange(e) {
    const value = e.target.value;
    const action = getInputChangeAction(value);
    store.dispatch(action);
}
handleStoreChange() {
    this.setState(store.getState());
}

总结

其实最后只是做了一个很小的处理,写这么多也是想搞清楚为什么会出现这样一个情况。

另外最后React也给大家做了一个提醒。

setState的异步,这只是一个实现的细节,所以请不要直接依赖于这种机制。在以后的版本当中,React 会在更多的情况下静默地使用 state 的批更新机制。


参考文章:

setState的一个Synthetic Event Warning