首页 > 解决方案 > React Parent Component 的 this.state 在 Child Component 的构造函数之后被调用

问题描述

我在反应中遇到了一些违反直觉的行为(至少对我而言)。我有一个 API 调用,它返回一些要显示的 JSON。我希望此调用的结果处于父组件(“问题容器”)的状态,并作为道具传递给其子组件(“问题”)。

我在子组件中得到了一个未定义的结果,所以我在 4 个不同的地方进行了一些控制台日志记录,以查看发生了什么:在每个构造函数中一次,在每个组件“this.state”中使用我的“getProblemsFromAPI()”函数一次.

父组件:

class ProblemContainer extends React.Component {
  constructor(props) {
    super(props);
    this.state =  {
      problem_set: getProblemsFromAPI()
    };
    {console.log(this.state.problem_set, 'parent constructor')}
  }


  render() {
    return(
      <div>
        <Problem problem_set={this.problem_set} />
      </div>
    )
  }

}

function getProblemsFromAPI(problem_set = {}) {
  fetch("http://localhost:5000/api/problem_set/5")
    .then(response => response.json())
    .then((data) => {console.log(data, 'set state of parent'); return data});
  }

子组件:

class Problem extends React.Component {
  constructor(props){
    super(props);
    this.state = {
      current_problem: '',
      problem_set: getProblemsFromAPI()
    }
    console.log(this.props, 'child constructor')
  }


    render() {
        return (
          <div>

          </div>
        );
      }

    }

function getProblemsFromAPI(problem_set = {}) {
  fetch("http://localhost:5000/api/problem_set/5")
    .then(response => response.json())
    .then((data) => {console.log(data, 'set state of child'); return data});
  }

我在控制台中看到的是:

  1. “父构造器”
  2. “儿童建造师”
  3. “设置父状态”
  4. “设置孩子的状态”

这对我来说很奇怪,因为父组件的“this.state”构造函数应该是顺序调用的第一件事。我可以将 API 调用放在子组件的 componentDidMount 中继续前进,这不是问题。我只是不明白这种行为。

这是因为它是一个函数调用而不是一个值吗?我对 javascript 和反应都很陌生。任何建议都会有所帮助!

谢谢

标签: javascriptreactjsreact-propsreact-state

解决方案


任何副作用,例如从外部 API 获取数据或任何状态变量更新,都应该在组件安装在componentDidMount生命周期方法(如果使用类组件)或useEffect挂钩(如果使用功能组件)之后完成。既然您说您希望将ProblemContainer数据传递给它的孩子。ProblemContainer应该负责获取数据。

例如,

class ProblemContainer extends React.Component {
  constructor(props) {
    super(props);
    this.state =  {
      problem_set: null,
      error: undefined
    };
  }

  componentDidMount() {
   fetch("http://localhost:5000/api/problem_set/5")
     .then(response => response.json())
     .then((data) => {this.setState({problem_set: data})});
     // never leave a promise with out catching the error
     .catch(error => {
       // you can console.log the error to see what is going wrong

       this.setState({problem_set: null, error: error})
     })
  } 




  render() {

    return(
      <div>
        <Problem problem_set={this.state.problem_set} /> // you need to pass the prop like this
      </div>
    )
  }

}


在您的问题组件中,

class Problem extends React.Component {
  // you have access to the problem_set via this.props.problem_set
    render() {
       console.log(this.props.problem_set) // should show the expected result
        return (
          <div>
             // component logic
          </div>
        );
      }

    }


推荐阅读