TypeError: evt.target is null in functional setState

TypeError: evt.target is null in functional setState

这两个函数的主要区别是什么?

handleOnChange(evt) {
    this.setState(() => ({
        tickerName: evt.target.value
    }));
}

handleOnChange(evt) {
    this.setState({ tickerName: evt.target.value });
}

为什么直接改变状态的 handleOnChange() 函数可以正常工作?

<input
    type="text"
    value={this.state.tickerName}
    onChange={(evt) => this.handleOnChange(evt)} 
/>

当我使用第一个通过回调更改状态的函数时,出现此错误:

TypeError: evt.target is null

React 将事件包装在它自己的 SyntheticEventwill be reused and all properties will be nullified after the event callback has been invoked(参见 react docs)。

根据 react docs,无法以异步方式访问 React SyntheticEvent,而 setState 是异步的。因此,当执行 setState 时,您的 evt 可能为空,因为它被 react 重用。由于第一个函数使用回调访问 setState 中的先前状态,因此在执行回调时,事件 evtreact 重用和无效。在第二种情况下,立即创建具有事件值的更新对象并直接传入,不会产生类似的问题。

如果您需要将 setState 与回调一起使用,您需要注意执行回调时可能为 null 的事件。处理此问题的一种方法是将对 target 的原始引用存储在 setState 之外,它将在 setState 内进行限定和使用。像这样:

handleOnChange(evt) {
    const target = evt.target;
    this.setState((prevState) => ({
        tickerName: target.value
    }));
}

我写了一个更详细的答案来解释为什么 react 事件在 setState 中为空。

setState 有两种不同的语法

第一个:

handleOnChange(evt) {
    this.setState(() => ({
        tickerName: evt.target.value
    }));
}

使用更新函数作为第一个参数。

第二个:

handleOnChange(evt) {
   this.setState({ tickerName: evt.target.value });
}

使用要更新的对象

在更新函数中使用合成事件时需要使用event.persist()

来自documentation:

the SyntheticEvent is pooled. This means that the SyntheticEvent object will be reused and all properties will be nullified after the event callback has been invoked. This is for performance reasons. As such, you cannot access the event in an asynchronous way.

If you want to access the event properties in an asynchronous way, you should call event.persist() on the event, which will remove the synthetic event from the pool and allow references to the event to be retained by user code.

你的第一个案例看起来像

handleOnChange(evt) {
    evt.persist();
    this.setState(() => ({
        tickerName: evt.target.value
    }));
}

或者不使用 event.persist(),您可以将事件存储在另一个对象中

handleOnChange(evt) {
    const value = evt.target.value;
    this.setState(() => ({
        tickerName: evt.target.value
    }));
}

P.S. 仅当您希望根据 prevState 或 [=17= 更新当前状态时,才应使用 setState 的更新程序函数]

CodeSandbox