简体   繁体   中英

How to render a component without calling setState or making componentWillUpdate to be executed in React?

So, let say I have 2 React component as below:

var Parent = React.createClass({
   getInitialState: function(){
      return ({
       child: <Children state="someState" />      
      });      
   },

  parentFunction: function() {
     this.setState({
       child: <Children state="otherState" />
     });
  },

  render: function() {
      return (
              <div>
              {this.state.child}                  
              </div>
      );
  }

  //...other methods
});

var Children = React.createClass({
   componentWillMount: function() {
      this.getData();
   },

   componentWillUpdate: function() {
      this.getData();
   }

   getData: function() {
      var that = this;

      $.getJSON("https://some.url", function(result){
           //Do something with result         

           that.setState();
      }); 


   }

   //other methods ....

});

When Parent is rendered for the first time, Children is rendered for the first time too. Therefore, Children's componentWillMount is executed and it, in turn, calls Children's getData. Since getData calls getJSON which is the async function, so it can't return the result "on time" for Children to be rendered for the first time. So, my solution is to call setState() after getJSON done with the result to make Children renders again. Everything seems ok so far.

But the problem arises when I call parentFunction to update Children. Since Children is updated, its componentWillUpdate will be executed and therefore, getData() is called. But getData() in turn calls setState() after it done with the result. And setState() makes componentWillUpdate to be executed. And that's how I fall into an infinite loop.

I'm finding a way to render a component without calling setState or making componentWillUpdate to be executed. But I haven't found it yet. I'm not sure how to solve this problem. Any help would be appreciated.

There's no need to find a way to render without calling setState.

To avoid a loop, simply use componentWillReceiveProps() in place of componentWillUpdate, as stated in React documentation .

However, you could even test if the component should really update , by using a pattern like the following one:

var Children = React.createClass({
    componentWillMount: function() {
        this.getData();
    },

    componentWillReceiveProps: function(nextProps) {
        // some sort of logic that defines if new 
        // props are different than the previous ones
        if(nextProps.data !== this.props.data)
        {
            this.getData();
        }
    }

    getData: function() {
        var that = this;

        $.getJSON("https://some.url", function(result){
            //Do something with result         

            that.setState();
        }); 
    }
}

According to me, you're also using the parent's state in a wrong way.

The state should contain data and attributes about the component itself, not other components.

It would be helpful to rewrite it like this:

var Parent = React.createClass({
   getInitialState: function(){
      return ({
       something: [] // example
      });      
   },

  parentFunction: function() {
     this.setState({
       something: [12] // example
     });
  },

  render: function() {
      return (
              <div>
                   <Children state={this.state.something} />
              </div>
      );
  }

  //...other methods
});

Hope this helped.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM