类型错误:evt.target 在功能 setState 中为 null

IT技术 reactjs state setstate
2021-04-10 01:32:13

这两个功能之间的主要区别是什么?

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
2个回答

这是 setState 的两种不同语法

第一的:

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

使用 updater 函数作为第一个参数。

第二:

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

使用要更新的对象

在更新程序功能中使用合成事件时,您需要使用 event.persist()

文档

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

如果您想以异步方式访问事件属性,您应该对事件调用 event.persist(),这将从池中删除合成事件并允许用户代码保留对事件的引用。

你的拳套看起来像

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
    }));
}

PS仅当您希望基于prevState更新当前状态时,才应为 setState 使用更新程序props

代码沙盒

所以在我的情况下,用回调更新状态是没有用的?因为我读到更新状态的新标准方法是使用回调,不是吗?。
2021-05-24 01:32:13
updater 函数setState具有 format (prevState, props) => stateChange,因此如果您不需要访问前一个状态,我会说使用仅带有更新对象的第二个状态。React 文档对调用setState.
2021-05-28 01:32:13
@Shubham Khatri,您知道为什么在使用对象event.persit()调用时不需要从事件中调用或缓存值setState,但在使用更新程序函数时需要这样做吗?setState在这两种情况下都不应该异步工作吗?甚至对受控组件的反应文档也不使用event.persist().
2021-06-07 01:32:13
@margaretkru,是的,这是我们应该关心的最基本的事情。
2021-06-12 01:32:13
@margaretkru,所以当你简单地写时this.setState({ tickerName: evt.target.value });,你只是将一个对象传递给 setState,而 . 立即分配给tickerName 键的值,但是在更新程序函数中,它只是一个回调,由setState 使用必要的参数调用,到那时事件属性无效。希望我能说清楚
2021-06-17 01:32:13

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

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

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

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

我写了一个更详细的回答为什么这里的react事件变空setState