componentWillMount无法设置状态

时间:2017-03-19 12:48:37

标签: reactjs

我有一个名为Home.js的父组件,它从API检索数据并将数据作为属性发送到它的子组件DishItem.js,显示菜单详细信息。我正在尝试渲染dish_name,数量(可以更改)和net_cost,我将所有这些存储在一个状态中,并通过componentWillMount()生命周期方法为初始渲染设置它们的状态。但它无法设置状态并返回undefined。

Home.js

import React, { Component } from 'react';
import DishItem from './DishItem';
import $ from 'jquery';

export default class Home extends Component {
 constructor() {
 super();
 this.state = {
   dish: ''
  }
}

getDishes() {
 $.ajax({
   url: 'http://testbed2.riktamtech.com/foody_buddy/public/api/dishes/dish/31816',
   dataType: 'json',
   cache: false,
   success: function(response) {
     this.setState({dish: response.data});
  }.bind(this),
  error: function(xhr, status, err) {
    console.log(err);
    }
  });
 }

componentWillMount() {
 this.getDishes();
}

componentDidMount() {
 this.getDishes();
}

render() {
 return (
   <div className="Home">
     <DishItem dish={this.state.dish}/>
   </div>
  );
 }
}

DishItem.js

    import React, { Component } from 'react';
    import Quantity from './Quantity';
    import { browserHistory } from 'react-router';
    import './style.css';

    export default class DishItem extends Component {
      constructor(props) {
        super(props);
        this.state = {
          quantity: 1,
          delivery: '',
          total_cost: '',
          net_cost: null,
          counter: 1
        }
      }

      componentWillMount() {
        console.log(this.props.dish.net_cost); //undefined instead of some value
        this.setState({net_cost: this.props.dish.net_cost}); 
        console.log(this.state.net_cost); // null
      }

      handleChangeInQuantity(value) {
        var net_cost = 0;
        var total_cost = 0;
        total_cost = value * this.props.dish.cost;
        net_cost = value * this.props.dish.net_cost;
        this.setState({quantity: value, net_cost: net_cost, total_cost: total_cost});
      }

      saveAndContinue(e) {
        e.preventDefault();
      }

      render() {
        let address = <div>{this.props.dish.address}<br/>{this.props.dish.landmark}<br/>{this.props.dish.locality}</div>
        return (
          <div>
            <h3>{this.props.dish.name}<small>{this.props.dish.description}</small></h3>
            Total- {this.state.net_cost}

            <Quantity change_in_quantity={this.handleChangeInQuantity.bind(this)} />
            <button className="btn btn-default" onClick={this.saveAndContinue.bind(this)}>Next</button>
          </div>
        );
      }
    }

3 个答案:

答案 0 :(得分:2)

componentWillMount()函数只触发一次,它不等待从服务器获取数据。您应该在DishItem组件中使用componentWillReceiveProps(),并使用从Home组件发送到它的数据设置新状态。这样,只要DishItem从Home组件接收到新的props,它就会相应地更新。

答案 1 :(得分:1)

您不应该使用React组件的componentWillMount方法来执行异步数据提取。移除您对getDishes方法的来电,并将其保留在componentDidMount中。在您的Home组件的render方法中,检查状态是否已经具有该状态的菜肴数据。如果没有,请不要渲染DishItem组件。您可以添加“请稍候,加载”等消息。

当页面加载时,React将使用“loading”消息呈现组件并开始异步加载碟形数据。当数据加载并设置状态时,React将使用DishItem组件再次呈现组件。

以下是您的主页组件的更新版本:

import React, { Component } from 'react';
import DishItem from './DishItem';
import $ from 'jquery';

export default class Home extends Component {
    constructor() {
        super();
        this.state = {
            dish: null
        };
    }

    getDishes() {
        $.ajax({
            url: 'http://testbed2.riktamtech.com/foody_buddy/public/api/dishes/dish/31816',
            dataType: 'json',
            cache: false,
            success: function (response) {
                this.setState({ dish: response.data });
            }.bind(this),
            error(xhr, status, err) {
                console.log(err);
            }
        });
    }

    componentDidMount() {
        this.getDishes();
    }

    render() {
        return (
            <div className="Home">
                {
                    this.state.dish === null ?
                        <div>Please wait, loading…</div> :
                        <DishItem dish={this.state.dish} />
                }
            </div>
        );
    }
}

答案 2 :(得分:1)

似乎我无法添加评论,所以我会发送这个,因为已经有很多答案。因为这个原因,请不要给我减一:)

即使它在componentDidMount中,一旦它获取数据,它将重新渲染DOM,使它看起来像是初始渲染。如果提取速度很慢,您会看到它空白片刻,然后呈现您需要的内容。

如果您确实需要在第一时间显示它,我建议您在重定向到此页面之前获取数据并将其保存在Flux存储区或Redux存储区中。例如,获取数据并在then()或回调函数内进行重定向。