【问题标题】:React.js setState not working [duplicate]React.js setState 不起作用[重复]
【发布时间】:2018-11-02 16:37:38
【问题描述】:

我是 React 的菜鸟,正在尝试为水相制作一个简单的应用程序,用户输入一个数字,然后根据该值显示水的状态,例如,如果他输入 212,它应该说 gas 和 for 12 它应该说是可靠的,但由于某种原因它没有正确显示值,非常感谢任何帮助!!!

class App extends React.Component {

    constructor(props) {
        super(props);
        this.state = {
            msg: "liquid",
            temp: 0
        };
        this.handlenum1Change = this.handlenum1Change.bind(this);
    }

    handlenum1Change(evt) {
        console.log(evt.target.value);
        this.setState({
            temp: Number(evt.target.value)
        });

        let temp = this.state.temp
        if (temp > 100) {
            this.setState({
                msg: "boiling"
            })
        } else if (temp < 32) {
            this.setState({
                msg: "frozen"
            })
        } else {
            this.setState({
                msg: "liquid"
            })
        }
    }

    render() {
        return (
            <div>
                <h1> {this.state.msg} </h1>
                <form className="form-inline">
                    <div className="form-group">
                        <label> Temp: </label>
                        <input type="number"  onChange={this.handlenum1Change} className="form-control" />
                    </div>
                </form>
            </div>
        );
    }
}

ReactDOM.render(
  <App />,
  document.getElementById("root")
);
<div id="root"></div>

<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>

【问题讨论】:

  • 欢迎来到 Stack Overflow!在寻求帮助时,请花时间以合理、一致的缩进来格式化您的代码,并且不要使用大量不必要的空格。 (当寻求帮助时也是个好主意。)
  • 感谢您在问题中包含所有必要的代码。如您所见,我更新了问题以使用 Stack Snippets(页面中类似于 &lt;&gt; 的工具栏按钮)制作一个 可运行版本。 Stack Snippets 支持 React,包括 JSX; here's how to do one.

标签: javascript reactjs


【解决方案1】:

setState 是异步的,不会立即更新状态。它在更新之前收集多个状态更改。 这意味着,this.state 不会立即保留您的新值。

或者在这里引用 React 文档:

setState() 并不总是立即更新组件。有可能 批处理或推迟更新。这使得阅读this.state 在致电setState() 之后,这是一个潜在的陷阱。相反,使用 componentDidUpdatesetState 回调 (setState(updater, callback)),其中任何一个都保证在更新后触发 已应用。如果需要根据前面的设置状态 状态,请阅读下面的更新程序参数。


相反,在设置新状态之前使用用户输入进行操作。这样你也可以同时设置温度和信息:

const temp = Number(evt.target.value);
let msg = '';
if (temp > 100) {
  msg = 'boiling';
} else if (temp < 32) {
  msg = 'frozen';
} else {
  msg = 'liquid';
}

this.setState({
  temp,
  msg,
});

【讨论】:

    【解决方案2】:


    除了比较之外,您没有在其他任何地方使用 this.state.temp,您可以在变量中分配值并进行比较。仅供参考,setState 不会立即反映更改。

    handlenum1Change(evt) {
            let temp = evt.target.value;
            if (temp > 100) {
                this.setState({
                    msg: "boiling"
                })
            } else if (temp < 32) {
                this.setState({
                    msg: "frozen"
                })
            } else {
                this.setState({
                    msg: "liquid"
                })
            }
        }
    

    【讨论】:

      【解决方案3】:

      setState is asynchronous。另外,如果您根据当前状态 (this.state.temp) 设置状态 (setState({msg: ...})),您必须使用 setState 的回调版本。

      但在这种情况下,您可以同时设置 tempmsg,因为它们都在状态之外的东西(来自 input 的临时值)中工作:

      handlenum1Change(evt) {
          console.log(evt.target.value);
          const temp = Number(evt.target.value);
          let msg;
      
          if (temp > 100) {
              msg = "boiling";
          } else if (temp < 32) {
              msg = "frozen";
          } else {
              msg = "liquid";
          }
          this.setState({temp, msg});
      }
      

      class App extends React.Component {
      
          constructor(props) {
              super(props);
              this.state = {
                  msg: "liquid",
                  temp: 0
              };
              this.handlenum1Change = this.handlenum1Change.bind(this);
          }
      
          handlenum1Change(evt) {
              console.log(evt.target.value);
              const temp = Number(evt.target.value);
              let msg;
      
              if (temp > 100) {
                  msg = "boiling";
              } else if (temp < 32) {
                  msg = "frozen";
              } else {
                  msg = "liquid";
              }
              this.setState({temp, msg});
          }
      
          render() {
              return (
                  <div>
                      <h1> {this.state.msg} </h1>
                      <form className="form-inline">
                          <div className="form-group">
                              <label> Temp: </label>
                              <input type="number"  onChange={this.handlenum1Change} className="form-control" />
                          </div>
                      </form>
                  </div>
              );
          }
      }
      
      ReactDOM.render(
        <App />,
        document.getElementById("root")
      );
      <div id="root"></div>
      
      <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>

      【讨论】:

        【解决方案4】:

        setState 不是立即更改状态的必要方法,而是您向 React 发出的请求,以尽快更改组件的状态(见here)。

        你应该考虑的另一件重要的事情是,event React 使用的不是标准的 HTML 事件,而是由 React 自己创建的用于包装标准事件的SyntheticEvent,并且这个SyntheticEvent 将尽快被丢弃尽可能出于“性能原因”。

        现在,你的问题很容易通过改变来解决

        const temp = this.state.temp
        

        const temp = Number(evt.target.value)
        

        但在使用 React 组件的状态时,您应该牢记以上两个因素。

        编辑:在使用setState 的回调版本时,关于SyntethicEvents 的考虑尤其重要,因为从该回调中访问值很可能包含输入的值触发了onChange 事件,因此您必须将其存储在回调范围之外的变量中,例如:

        handleInputChange = (event) => {
             const value = event.target.value
        
             this.setState(prevState => {
                  return { myValue: prevState.value + value }
             })
        }
        

        【讨论】:

          猜你喜欢
          • 2021-04-29
          • 1970-01-01
          • 2018-05-08
          • 1970-01-01
          • 2016-09-22
          • 1970-01-01
          • 1970-01-01
          • 2020-12-26
          • 1970-01-01
          相关资源
          最近更新 更多