【问题标题】:Issue of using e.target.value in React setState function在 React setState 函数中使用 e.target.value 的问题
【发布时间】:2018-07-10 02:08:40
【问题描述】:

我在 React 中遇到了一个奇怪的问题。我想我可能还没有完全掌握 React 的工作原理,非常感谢您的帮助。

请在下面找到我的 React 组件:

class myComponent extends Component {
  state = {
    value: ''
  }

  updateValue = e => {
    this.setState({
      value: e.target.value
    })
  }

  render() {
    return (
     <form>
      <input type="text" onChange={this.updateValue} defaultValue={this.state.value} />
     </form>
    )
  }
}

然后,现在如果我在文本字段中输入内容,我将收到以下警告和错误:

警告:出于性能原因,此合成事件会被重复使用。如果您看到这一点,则表示您正在访问已发布/无效合成事件上的属性 target。这设置为空。如果您必须保留原始合成事件,请使用 event.persist()。

未捕获的 TypeError:无法读取 null 的属性“值”

但如果我将 'updateValue' 方法更改为:

updateValue = e => {
    const newValue = e.target.value
    this.setState({
      value: newValue
    })
  }

它可以正常工作。

【问题讨论】:

  • 我不相信您作为“解决方案”提供的更改会产生任何影响,他们不可能有不同的行为。
  • I put the code in a sandbox, and I'm not seeing any such warnings in the console. 您能否更新您的示例代码以更好地适应您的实际代码?
  • 您发布的代码不会导致该错误。
  • 这太疯狂了。我只需要将我的方法更改为箭头函数即可使其正常工作。

标签: javascript reactjs


【解决方案1】:

更新答案

正如@FelixKling 指出的那样,我的回答并不完全正确。我的回答只有在您将 function 作为参数传递给setState 时才有效,而不是像在问题中所做的那样传递 object

如果您将对象 传递给setState,则将立即评估该参数,即在事件无效之前。因此,不会发生上述错误。

如果您将 函数 传递给 setState,则将在该函数内评估参数,这发生在 updateValue 完成/返回并且事件已被取消之后。如果将函数传递给setState,则必须在setState 之前将e.target.value 存储在变量中(或调用e.persist())。

旧的(略有错误)答案

出现此问题是因为(如错误消息所述)回调(您的 updateValue 函数)完成时事件设置为 null。

因为this.setState() is an asynchronous function,不会立即执行。因此,this.setState() 实际上是在您的 updateValue 完成之后执行的,因此在事件被取消之后。

你的解决方案其实是the proposed way from the React docs

【讨论】:

  • 这不太对。 this.setState 立即执行。每个被调用的函数都会立即执行。但是,状态更改不会立即应用。但这与 OP 看到的错误无关。函数参数总是立即被评估。 e.target.value 在调用 updateValue 的那一刻被评估。
  • @FelixKling 你是对的,函数参数会立即被评估。我在 Codepen 中测试了问题中的代码,没有发现错误。如果我将函数而不是对象传递给setState,则会发生错误。我会更新我的答案。
【解决方案2】:

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

基本上,由于 React 的事件池,在异步 setState() 中无法访问点击事件 (e),除非您使用 event.persist()(如您收到的警告中所述)。

React 事件池: https://reactjs.org/docs/events.html

【讨论】:

    【解决方案3】:

    如果有人正在寻找方法来实现这一点。在这里剪了一个。

    class myComponent extends Component {
      constructor(props) {
        super(props);
        this.state = {
          value: ''
        };
        this.updateValue = this.updateValue.bind(this);
      }
      updateValue(e) {
        this.setState({ value: e.target.value })
      }
      render() {
        return ( <form>
          <input type="text" value={this.state.value} 
            onChange={this.updateValue} 
            defaultValue={this.state.value} />
          <h4>Controlled Input:</h4> <p>{this.state.value}</p>
          </form>
        ); 
      }
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-12-16
      • 2018-09-11
      • 2021-10-10
      • 2018-11-13
      • 2021-06-02
      • 1970-01-01
      • 2022-11-28
      • 2017-11-10
      相关资源
      最近更新 更多