【问题标题】:Endless loop after changing state改变状态后无限循环
【发布时间】:2018-06-09 08:13:49
【问题描述】:

我已经创建了组件,该组件将更改其状态的函数传递给子组件。

//parent component
setSubject = (id) => {
    this.setState({
        currentSubject: id
    });
}

<Subjects authToken = {this.state.authToken} subjects = {this.state.subjects} setSubject = {this.setSubject} />

//child component
<li onClick={() => this.props.setSubject(subject.id)}>Egzamino programa</li>

该状态被传递给另一个组件。

 <Sections authToken = {this.state.authToken} subject = {this.state.currentSubject} />

从那里我使用 componentDidUpdate() 方法来处理这个变化:

componentDidUpdate() {
    if (this.props.subject) {            
        axios.get(`http://localhost:3000/api/subjects/${this.props.subject}/sections?access_token=${this.props.authToken}`)
            .then(response => {
                this.setState({
                    sections: response.data
                })
            }).catch(err => {
                console.log(err)
            })
    }
}

一切都按预期工作,但是当我通过 Subjects 组件设置 currentSubject 后尝试在 Sections 组件中 console.log 时,console.log 执行无数次(我猜是 get 请求...... ) 这不是很好,是吗?而且我无法理解为什么会发生这种情况..

【问题讨论】:

  • 通读这个问题可能会对您有所帮助:stackoverflow.com/questions/30528348/…。在您的代码中,似乎在每个 componentDidUpdate 上都调用了 setState,这会导致无限循环。您使用componentDidUpdate 有什么原因吗?

标签: reactjs


【解决方案1】:

错误在您的componentDidUpdate 方法中。

您正在使用

更新状态
   this.setState({ 
     sections: response.data
   })

当你这样做时,componentDidUpdate 生命周期方法将被调用并且你有无限循环。

您可以通过使用锁来快速修复以避免此问题。但是可能有更好的设计来解决您的问题。

快速修复示例:

if (this.props.subject && !this.state.sectionsRequested) {
  this.setState({
    sectionsRequested: true,
  });
  axios.get(`http://localhost:3000/api/subjects/${this.props.subject}/sections?access_token=${this.props.authToken}`)
    .then(response => {
      this.setState({
        sections: response.data,
      });
    })
    .catch(err => {
      console.log(err);
    });
}

对于您的情况,最好使用componentWillReceiveProps。 您有兴趣根据您的 this.props.subject 值获取数据。我可以看到,因为您将它用作 url 查询的一部分。

您可能有兴趣使用componentWillReceivePropscomponentDidMount 而不是componentDidUpdate

componentDidMount(){
  if(this.props.subject){
    /* code from componentDidUpdate */
  }
}

componentWillReceiveProps(nextProps){
  if(nextProps.subject && this.props.subject !== nextProps.subject){
    /* code from componentDidUpdate */
  }
}

【讨论】:

  • 此修复的问题:我无法两次发出 get 请求(使用另一个 subject.id)。尝试使用 componentWillReceiveProps,现在当我收到 axios 响应时 setState 出现问题。在下载了部分的数组后,每个部分的 Id 被传递给另一个加载子部分的组件。但是在第一次调用 componentWillReceiveProps 方法后不会加载小节。我猜这是因为响应是延迟处理的,并且渲染发生在 setState 之前。那么如何在设置状态后使其呈现..?
  • 记住也要使用componentDidMount 来获取初始数据,(以防你没有使用它)。如果您通过setState 更新状态,React 会为您触发渲染方法和子渲染方法。
  • 如果初始数据 (subject.id) 未知,为什么我需要使用 componentDidMount?我希望它在按下为 this.props.subject 分配值的按钮后呈现部分和小节。在 axios.get(***).then() 中的 setState 之后调用 this.forceUpdate() ,一切似乎都在工作。
猜你喜欢
  • 2022-08-18
  • 2018-09-02
  • 2020-07-09
  • 2021-01-16
  • 2021-11-06
  • 1970-01-01
  • 2020-09-06
  • 2021-11-13
  • 1970-01-01
相关资源
最近更新 更多