使用箭头功能反应this.setState会导致控制台错误

时间:2018-08-04 14:58:18

标签: javascript reactjs typescript

我有一个非常简单的表单,其中我以组件状态存储用户电子邮件,并使用onChange函数更新状态。发生了一件奇怪的事情,如果我的onChange函数使用一个函数更新状态,则每次键入时都会在控制台中出现两个错误。但是,如果使用对象更新状态,则不会出错。我相信建议使用函数更新,因此我很想知道为什么会出现这些错误。

我的组件:

import * as React from 'react';
import { FormGroup, Input, Label } from 'reactstrap';

interface IState {
  email: string;
}

class SignUpForm extends React.Component<{}, IState> {
  constructor(props: {}) {
    super(props);

    this.state = {
      email: ''
    };
  }

  public onEmailChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    this.setState(() => ({ email: event.currentTarget.value }))
  };

  // Using this function instead of the one above causes no errors
  // public onEmailChange = (event: React.ChangeEvent<HTMLInputElement>) => {
  //   this.setState({ email: event.currentTarget.value })
  // };

  public render() {

    return (
      <div>
        <h1>Sign Up</h1>
        <div className='row' style={{ paddingTop: '20px' }}>
          <div className='col-lg-4 offset-lg-4'>
            <form>
              <FormGroup style={{ textAlign: 'left' }}>
                <Label>Email</Label>
                <Input
                  value={this.state.email}
                  onChange={this.onEmailChange}
                  type='text'
                  placeholder='Email Address'
                />
              </FormGroup>
            </form>
          </div>
        </div>
      </div>
    );
  }
}

export default SignUpForm;

我收到的错误消息是:

index.js:2178 Warning: This synthetic event is reused for performance reasons. If you're seeing this, you're accessing the method `currentTarget` on a released/nullified synthetic event. This is a no-op function. If you must keep the original synthetic event around, use event.persist(). See react-event-pooling for more information.

index.js:2178 Warning: A component is changing a controlled input of type text to be uncontrolled. Input elements should not switch from controlled to uncontrolled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component. More info: react-controlled-components

2 个答案:

答案 0 :(得分:4)

如果状态更新是从当前状态(例如,增加count变量)派生的,则应使用setState的更新功能版本。

如果像事件处理程序那样只是设置一个全新的值,则无需使用更新功能版本。您问题中被注释掉的版本完全可以。

如果要使用更新功能版本,则必须使用event.persist(),以便可以异步使用事件,或者在调用setState之前直接提取值。

public onEmailChange = (event: React.ChangeEvent<HTMLInputElement>) => {
  const { value } = event.currentTarget;
  this.setState(() => ({ email: value }))
};

答案 1 :(得分:3)

一旦事件处理程序终止,就不能使用event或其任何后代属性。相反,您必须获取值,然后使用该函数(或者,如果愿意,可以使用persist作为Tholle points out):

public onEmailChange = (event: React.ChangeEvent<HTMLInputElement>) => {
  const { value } = event.currentTarget;
  this.setState(() => ({ email: value }));
};

也就是说,由于您不是根据状态或道具更新状态,因此这是使用setState的非回调版本很好的少数情况之一({ {3}}):

public onEmailChange = (event: React.ChangeEvent<HTMLInputElement>) => {
  this.setState({ email: event.currentTarget.value });
};