未捕获的TypeError:无法读取未定义的属性'setState'

时间:2018-07-09 22:29:44

标签: javascript reactjs webpack

我正在尝试使用Web-pack渲染简单的react应用程序,所有程序都可以完美编译。在运行时,代码失败并显示以下堆栈跟踪:

Uncaught TypeError: Cannot read property 'setState' of undefined
at checkBoxCheck (App.js:174)...

这是带有setState的代码:

//App.js
export class Login extends Component {
  constructor(props) {
    super(props);
    this.state = { remember: false };
  }

  checkBoxCheck(event) {
    this.setState({
      remember: !this.state.remember
    });
    console.log(this.state.remember);
  }

  render() {
    let msg = this.state.remember ? "checked" : "uncheked";
    return (
      <form method="post">
        <h1>{msg}</h1>
        <label htmlFor="login">Login: </label>
        <input type="text" name="login" />
        <label htmlFor="pass"> Password: </label>
        <input type="password" name="pass" />
        <label htmlFor="remember">Remeber me: </label>
        <input
          type="checkbox"
          name="remember"
          defaultChecked={this.state.remember}
          onChange={this.checkBoxCheck}
        />
      </form>
    );
  }
}

语法问题在哪里?

我还试图创建一个checkBoxCheck'arrow'函数,该函数会导致编译错误:

    checkBoxCheck = event => {
    this.setState((prevState, props) =>({
        remember: !prevState.remember
    }));
    console.log(this.state.remember);
}

//output        
SyntaxError: D:/Projects/Learning-projects/learn-react/src/App.js: Unexpected token (53:18)

  51 |     }
  52 |
> 53 |     checkBoxCheck = event => {
     |                   ^
  54 |         this.setState((prevState, props) =>({
  55 |             remember: !prevState.remember
  56 |         }));

2 个答案:

答案 0 :(得分:3)

您实际上忘记了将上下文绑定到checkBoxCheck方法。

...
<input
   type="checkbox"
   name="remember"
   defaultChecked={this.state.remember}
   onChange={this.checkBoxCheck.bind(this)} // <- .bind(this)
/>
...

提示:

关于您的代码的评论很少:

  1. 请勿在{{1​​}}方法中绑定上下文。
  2. 请勿在{{1​​}}函数中使用render

从不this.state中的this.setState

.bind()

通过像这样绑定事件处理程序,可以在每次React调用组件的渲染器时创建全新的函数。相反,您可以将函数转换为箭头函数:

render

并这样称呼它:

render() { // <- If you here
  ...
  <input
    ...
    onChange={this.checkBoxCheck.bind(this)} // <- don't do this
  />
  ...
}

此外,您可以在类构造函数中绑定所有方法:

checkBoxCheck = event => {
  this.setState({
    remember: !this.state.remember
  });
  console.log(this.state.remember);
}

并在没有绑定的情况下调用函数:

...
<input
   type="checkbox"
   name="remember"
   defaultChecked={this.state.remember}
   onChange={this.checkBoxCheck} // <- there is no binding
/>
...

//App.js export class Login extends Component { constructor(props) { super(props); this.state = { remember: false }; this.checkBoxCheck = this.checkBoxCheck.bind(this); // <- Bind your methods here } ... 中使用... <input type="checkbox" name="remember" defaultChecked={this.state.remember} onChange={this.checkBoxCheck} // <- there is no binding /> ...

一个示例可以是增量函数:

this.state

如果将这两个setState操作成批分组在一起,则假定值为1:

this.setState

这可以通过使用将先前状态作为第一个参数的回调来避免:

function increment() {
  this.setState({value: this.state.value + 1});
}

然后,即使事情成批发生,react也会以正确和更新的状态调用参数。上面的示例如下所示:

setState({value: 1 + 1})
setState({value: 1 + 1})

参考:

答案 1 :(得分:1)

之所以会这样,是因为您需要将this.checkBoxCheck绑定到this

将以下内容添加到您的构造函数中:this.checkBoxCheck = this.checkBoxCheck.bind(this)

示例:

//App.js
export class Login extends Component {
  constructor(props) {
    super(props);
    this.state = { remember: false };

    this.checkBoxCheck = this.checkBoxCheck.bind(this);
  }

  checkBoxCheck(event) {
    this.setState({
      remember: !this.state.remember
    });
    console.log(this.state.remember);
  }

  render() {
    let msg = this.state.remember ? "checked" : "uncheked";
    return (
      <form method="post">
        <h1>{msg}</h1>
        <label htmlFor="login">Login: </label>
        <input type="text" name="login" />
        <label htmlFor="pass"> Password: </label> 
        <input type="password" name="pass" />
        <label htmlFor="remember">Remeber me: </label>
        <input
          type="checkbox"
          name="remember"
          defaultChecked={this.state.remember}
          onChange={this.checkBoxCheck}
        />
      </form>
    );
  }
}