改变反应状态

时间:2017-04-20 18:05:29

标签: javascript reactjs

我正在学习React并且作为一个学习练习我试图做一个非常基本的页面,其中有一个表单并且您将文本放在输入框中,单击“提交”并且标题将更改为您输入的内容。到目前为止,这是我的代码:

import React, { Component } from 'react';
import './App.css';

class App extends Component {
  constructor() {
    super();
    this.state = {header: 'yeaheheh'}
  }
  changeHeader(e) {
    let newHeader = document.getElementById('input').value();
    e.preventDefault();
    console.log('submitted');
    this.setState(newHeader);
  }
  render() {
    return (
      <div>
            <h1>{this.state.header}</h1>
            <form onSubmit={this.changeHeader.bind(this)} className="change-header-form">
                <input id="input" type="text" placeholder="Enter Text Here" />
                <input type="submit" value="Submit" />
            </form>
          </div>  
    );
  }
}

export default App;

首先,当我点击提交时,没有任何反应,我在控制台中出现了错误

Uncaught TypeError: Cannot read property 'setState' of null

然后我意识到我需要将changeHeader函数绑定到this,之后我才改变它:

<form onSubmit={this.changeHeader}...

将其更改为

<form onSubmit={this.changeHeader.bind(this)}...

执行此操作后,错误已清除,但我的标题仍然没有更新。I read that强烈反对通过setState更改状态的建议是不好的做法,因为再次调用setState()可能会改变已更改的状态。 setState也是一个异步操作,也可以解释为什么我的标题不会改变。

尽管如此,那么处理这个问题的最佳方法是什么?根据我的理解,props不会有意义,因为这些值直接存储在您的组件中,并且不能动态更新这些参数。我很难理解这些不同数据类型之间的关系以及它们在DOM中的处理方式。

5 个答案:

答案 0 :(得分:2)

您正在错误地设置状态。 为了从输入字段中获取数据,您可以通过&#34; ref&#34; 使用controlled输入元素(通过状态)或uncontrolled输入元素在下面的例子中使用过。

在受控输入元素中,您将输入元素的值存储在状态中,并通过调用onChange方法然后通过this.setState({})设置状态来更改该值。

调用setState会导致重新呈现,dom会根据新状态获取更新后的数据。

顺便说一句&#34;参考&#34; 让您可以直接访问dom元素,就像$()中使用jquery一样,如果可能的话应该避免因为它会导致很难管理和预测dom更改。

还有一些情况下使用&#34; refs&#34;推荐

refs有一些很好的用例:

  • 管理焦点,文字选择或媒体播放。

  • 触发势在必行的动画。

  • 与第三方DOM库集成。

&#13;
&#13;
class App extends React.Component {
  constructor() {
    super();
    this.state = {header: 'yeaheheh'};
  }
  changeHeader = (e) => {
     e.preventDefault();
    let newHeader = this.textInput.value;
    console.log('submitted');
    this.setState({header : newHeader});
  }
  render() {
    return (
      <div>
            <h1>{this.state.header}</h1>
            <form onSubmit={this.changeHeader} className="change-header-form">
                <input id="input" ref={(input) => { this.textInput = input; }} type="text" placeholder="Enter Text Here" />
                <input type="submit" value="Submit" />
            </form>
          </div>  
    );
  }
}

ReactDOM.render(<App />, document.getElementById('test'));
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="test">
</div>
&#13;
&#13;
&#13;

答案 1 :(得分:1)

this.setState(newHeader);替换为this.setState({header: newHeader});

答案 2 :(得分:1)

在反应文档中查看这篇文章:https://facebook.github.io/react/docs/forms.html#controlled-components

基本上你想要做的是为输入创建另一个处理程序。每次输入字段发生更改时都会调用此选项,并且state中的属性将更新。然后,当您提交表格时,您可以使用该新房产并且&#34;合并&#34;它使用setState成为新标题。

JS Bin

class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      header: 'yeaheheh',
      next: ''
    }

    this.changeHeader = this.changeHeader.bind(this);
    this.updateNext = this.updateNext.bind(this);
  }

  changeHeader(e) {
    e.preventDefault();

    this.setState({
      header: this.state.next
    });
  }

  updateNext(e) {
    this.setState({
      next: e.target.value
    });
  }

  render() {
    return (
      <div>
        <h1>{this.state.header}</h1>
        <form onSubmit={this.changeHeader} className="change-header-form">
          <input id="input" type="text" placeholder="Enter Text Here" onChange={this.updateNext} />
          <input type="submit" value="Submit" />
        </form>
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById('app')); 

也许这个垃圾箱会在我试图描述的内容中提供更好的背景。

答案 3 :(得分:0)

您的代码中存在小错误,导致其无法正常工作(this.setState(newHeader) - &gt; this.setState({header: newHeader});),但问题是您的代码不是React的惯用语。

您应该使用controlled components而不是像提交jQuery一样从提交表单的输入中获取值。

&#34;受控组件&#34;对于模式而言,输入的状态被映射到应用程序状态是一个愚蠢的名称,因此输入本身就像是有点无状态&#34;。在您的情况下,您需要为您获得的每个文本输入都有单独的组件状态成员。输入控件应如下所示:

<input value={ this.state.inputValue }
       onChange={ e => this.setState({ inputValue : e.target.value }) }
/>

现在它已经绑定到您的inputValue州成员,所以您可以随时从州内取出它。在你的情况下,在表单的提交处理程序上。

那就是它。您的代码必须相应修复。请参阅&#34;受控组件&#34;手册了解更多细节,它是真正重要的React概念。

答案 4 :(得分:0)

您应该像这样修改您的功能..

constructor(props) {
    super(props); 
    _that = this;
  }

  changeHeader = (e) => {
     e.preventDefault();
    let newHeader = this.textInput.value;
    console.log('submitted');
    _that.setState({header : newHeader});
  }