更新道具后组件不会更新

时间:2017-03-07 21:43:10

标签: javascript reactjs

我的问题是为什么组件在更新道具后没有更新。这是我的代码,可以很好地解释我:

export default class App extends React.Component {

    constructor(props) {
        super(props);
        this.topWeakSlotsData = {};
        this.topWeakSlotsData['loading'] =  true;
        this._fetchWeeklyWeakSlots();
    }

    _fetchWeeklyWeakSlots() {
      var _this = this;
      fetch("...")
      .then(function(response) {
          return response.json()
      }).then(function(json) {

          _this._elaborateTopWeakSlots(json['return']);

      }).catch(function(ex) {
          console.log('parsing failed', ex)
      })
    }

    _elaborateTopWeakSlots(data) {
      ...
      this.topWeakSlotsData['options'] = {
        ...
      }

      this.topWeakSlotsData['loading'] =  false;

    }

    render() {
      return (
        <HighchartContainer data = {this.topWeakSlotsData} container ="chart1" />
      )
    }
}

export default class HighchartContainer extends Component {
   constructor(props) {
     super(props);
   }

   shouldComponentUpdate(nextProps, nextState) {
     console.log("should update");
     return true;
   }

   componentWillReceiveProps(nextProps) {
     console.log(nextProps);
   }

   renderLoading() {
      return (
          <div>
           <Loader />
          </div>
      );
   }

   renderChart() {
      return (
         <div>
            <Highchart container = {this.props.container} options = {this.props.data.options}/>
         </div>
       );
   }

   render() {
      return (
         <div>
           {this.props.data.loading ? this.renderLoading() : this.renderChart()}
         </div>
      );
   }
}

正如您可以看到提取完成时我将loadingtrue更改为false并填写了选项数组,但shouldComponentUpdate或{{1}没有被调用,组件没有刷新,我错了吗?

2 个答案:

答案 0 :(得分:3)

当App的道具或状态发生变化时,App组件将仅重新呈现HighChartContainer组件。您当前正在将topWeakSlotsData存储为类属性,因此组件在更改时不会更新。您需要将其存储为App上的状态。

export default class App extends React.Component {

    constructor(props) {
        super(props);
        this.state = {
            topWeakSlotsData: {
                loading: true
            },
            lowWeakSlotsData: {
                loading: false // or whatever data you want here
            }
        }
        this._fetchWeeklyWeakSlots();
    }

    _fetchWeeklyWeakSlots() {
      var _this = this;
      fetch("...")
      .then(function(response) {
          return response.json()
      }).then(function(json) {    
          _this._elaborateTopWeakSlots(json['return']);

      }).catch(function(ex) {
          console.log('parsing failed', ex)
      })
    }

    _elaborateTopWeakSlots(data) {
        this.setState({
            topWeakSlotsData: {
               loading: false,
               options: data.options // or wherever else
            }
        }
    }

    render() {
      return (
        <HighchartContainer data = {this.state.topWeakSlotsData} container ="chart1" />
      )
    }
}

修改

正如另一个答案所指出的,你可以重构_fetchWeeklyWeakSlots方法来使用箭头/ lambda函数,例如

_fetchWeeklyWeakSlots() {  
    fetch("...")
        .then(response => response.json())
        .then(json => json['return'])
        .then(_elaborateTopWeakSlots)
        .catch(ex => {
            console.log('parsing failed', ex)
        });
    }

答案 1 :(得分:2)

一旦您的获取承诺结算,您将需要通过将您的响应传递给this.setState()

来更新您的状态
var _this = this

fetch(url)
    .then( function(response) { return response.json() }) // parse our response into json
    .then( function(json) { _this.setState({json: json}) } // set our state based on our parsed response

状态更新后,您可以在组件中引用{this.state.json}。

<强>加成 如果您使用ES6箭头功能: args =&gt; {//在这里做点什么} 你不需要 var _this = this 因为这个的处理方式。

以上示例变为:

fetch(url)
    .then( response => response.json() )
    .then( json => this.setState({ json: json })