【问题标题】:componentWillMount does not finish before rendercomponentWillMount 在渲染之前没有完成
【发布时间】:2016-12-09 19:44:32
【问题描述】:

我在 reactjs 中的状态方面遇到了一些困难。 据我所知,componentWillMount 是在渲染组件之前使用 ajax 调用加载数据的地方。 我有一个简单的项目,它使用加载的数据填充面板堆栈并将其显示在板上。然而,来自 ajax 调用的数据在渲染组件之前没有设置,这会导致使用空数组渲染电路板。以下是我的完整来源:

import  React from "react";
export class Panel extends  React.Component{
render() {
    return (
    <div>
        <div className="row panel">
            <div className="col-sm-12 header">sfsfsf</div>
            <div className="col-sm-12 body">fsdfsfs</div>
            <div className="col-sm-12 footer">fasfaf</div>
        </div>
    </div>
    );
   }
   }

作为问题根源的 Board 类如下:

import  React from "react";
 import {Panel} from "./Panel";
 export class Board extends  React.Component{
 constructor(props){
    super();
    this.state={news: []};
}
componentWillMount(){
    this.state={news: []};
    $.ajax({
        url: "http://localhost:3003/json.txt",
        dataType: 'json',
        cache: false,
        success: function(data) {
            var arr=[];
            for (var key in data) {
                arr.push(data[key]);
                console.log(data[key]);
            }
            this.state={news: arr};
        }});
     }
     render() {
    return (
        <div>
            {
                this.state.news.map((item,i)=> <Panel key="i"/>)
            }
        </div>
    );
    }
 }

最后一个类是 index.js:

import React from "react";
 import {render} from "react-dom";
import {Board} from "./component/Board";

class App extends React.Component{

  render(){
    return(
        <div>

            <Board/>

        </div>

    );
  }

}

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

正如您在 Board.js 类中看到的那样,我在渲染函数中初始化我的数组,然后我使用 componentWillMount 填充我希望它在 componentWillMount 完成后发生的新闻数组,但在我的情况下,当渲染发生。有什么想法吗?

*********更新***************

我也用 componentDidMount 试过了,但是没用,同样的问题

【问题讨论】:

  • 您所描述的是调用异步函数的预期结果。无论你在哪里调用它,React 生命周期都会在不等待服务器回调的情况下进行渲染。您应该尝试同步调用(不太好)或将 AJAX 调用一个组件,然后将结果作为道具传递给您的 Board

标签: reactjs react-jsx


【解决方案1】:

componentWillMount() 在渲染之前完成,但由于 ajax 是异步的,它在请求完成之前不会执行。

您不应使用this.state = ... 设置状态。而是使用:

this.setState({news: arr});

这将设置值并触发组件和所有子级渲染。只需编写您的渲染函数来很好地处理空数据,您将获得预期的结果,而不会阻塞 JS 执行。

正如这里建议的那样,它具有适当的绑定:

import  React from "react";
import {Panel} from "./Panel";
export class Board extends  React.Component{
  constructor(props){
    super();
  }

  getInitialState() {
    return {news: []};
  }

  componentWillMount(){
    $.ajax({
      url: "http://localhost:3003/json.txt",
      dataType: 'json',
      cache: false,
      success: (data) => {
        var arr=[];
        for (var key in data) {
          arr.push(data[key]);
          console.log(data[key]);
        }
        this.setState({news: arr});
      }
    });
  }
  render() {
    return (
        <div>
            {
                this.state.news.map((item,i)=> <Panel key="i"/>)
            }
        </div>
    );
  }
}

箭头函数处理绑定。类似于function(){}.bind(this)

【讨论】:

  • this.state 很好。我还注意到成功回调的匿名函数中有一个this.state。您将需要以另一种方式访问​​状态,因为 this 很可能不会是您所期望的。
  • @Sandwichz 不错。我已经习惯了使用箭头函数,以至于绑定的东西经常让我忘记。我会更新,我的例子。
  • 谢谢,能解释一下.bind()在这里的作用吗?
  • 它确保成功回调绑定到组件,允许您在其上设置状态。
  • @RobLynch 渲染函数会运行两次吗?
【解决方案2】:

您正在执行一个异步的 ajax 调用...根据定义,它将继续执行代码而不等待 ajax 的响应。

您可以通过在 $.ajax 选项上设置 async: false 来实现同步。

【讨论】:

    猜你喜欢
    • 2018-04-16
    • 2018-04-21
    • 1970-01-01
    • 2018-04-05
    • 2018-09-19
    • 2019-12-31
    • 1970-01-01
    • 2021-11-21
    • 1970-01-01
    相关资源
    最近更新 更多