【问题标题】:React: Child component is passing it's state up to parent, but once parent has it, the parent is not updating its stateReact:子组件将其状态传递给父组件,但是一旦父组件拥有它,父组件就不会更新其状态
【发布时间】:2018-01-27 11:50:21
【问题描述】:

我的问题是我有一些来自 SearchForm 组件的值。他们将正确的值作为参数传递给 handleSearch 函数,但我对 setState 的调用什么也没做。我已经包含了 console.logs 来显示存储在变量中的内容。请参阅下面代码中的 cmets。

因为我的状态作为空字符串从该组件传递到 ResultList 组件,所以 ResultList 无法正确呈现。

import React, { Component } from 'react';
import axios from 'axios';
import SearchForm from './components/search_form';
import ResultList from './components/results_list';

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

    this.state = { category: '', term: '', results: [] };
    this.handleSearch = this.handleSearch.bind(this);
  }

  handleSearch(category, term) {

    //This is not setting the state!!!!!
    this.setState({ category, term });

    //The first two console.logs successfully log the arguments to this 
    function
    //The last two console.logs log empty strings even after the above 
    setState call.

    console.log("Received from form: " + category);
    console.log("Received from form: " + term);
    console.log("#################################");
    console.log(this.state.category);
    console.log(this.state.term);


    console.log('http://swapi.co/api/' + category + '/?search=' + term);
    axios.get('http://swapi.co/api/' + category + '/?search=' + 
term).then((response) => {
        let results = response.data.results;
        this.setState({ results });
        console.log(this.state.results);
    }).catch((error) => {
      console.log(error);
    });

  }

  render() {
    return (
      <div className="container panel panel-default">
        <SearchForm handleSearch={this.handleSearch}/>
        <ResultList results={this.state.results} category=
{this.state.category}/>
      </div>
    );
  }
}

export default App;

【问题讨论】:

标签: reactjs components state


【解决方案1】:

setState 不是同步函数调用,因此在函数中调用 setstate 可能不会立即更新状态。根据文档

setState() 将组件状态的更改排入队列,并告诉 React 该组件及其子组件需要重新渲染 更新状态。这是您用来更新用户的主要方法 响应事件处理程序和服务器响应的接口。考虑到 setState() 作为请求而不是立即命令来更新 零件。为了获得更好的感知性能,React 可能会延迟它,并且 然后一次更新几个组件。反应没有 保证立即应用状态更改

所以console.log(this.state.category); console.log(this.state.term); 不会记录更新的状态。但是如果你把这些语句放在渲染函数中,你会看到在下一次渲染中设置了正确的状态。

阅读更多https://facebook.github.io/react/docs/react-component.html#setstate

【讨论】:

    【解决方案2】:

    我会详细说明我在评论中所说的话:

    Component#setState 延迟和批处理状态更新请求以提高性能。因此,您无法在调用后立即使用新值更新Component.state

    setState 提供了第二个参数 - 在执行状态更新操作后调用的回调。在你的情况下,它看起来像

    this.setState({ category, term }, () => {
      console.log(this.state.term, this.state.category)
      // now you can use them
    }) 
    

    【讨论】:

    • 我认为即使这样也行不通。回调函数将具有相同的状态,而不是更新的状态。如果要在回调中使用新变量,则必须在函数中显式传递它们
    • @bhaskarsharma 我不确定我是否遵循 - 你是什么意思“如果你想在回调中使用新变量?”
    • @bhaskarsharma 检查this answer :)
    • 假设您想在回调函数() =&gt; { console.log(this.state.term, this.state.category) // now you can use them }) 中使用类别和术语,那么 this.state.term 和 this.state.category 将不是更新的状态变量,而是相同的旧变量,所以您必须像这样在回调(term, category) =&gt; { console.log(term, category) // now you can use them }) 中传递新变量
    • 呃,不...回调没有参数。
    猜你喜欢
    • 1970-01-01
    • 2022-07-15
    • 1970-01-01
    • 2017-05-31
    • 2019-02-17
    • 2019-04-02
    • 2020-07-04
    • 1970-01-01
    • 2018-10-09
    相关资源
    最近更新 更多