Why is the WillMount component called after rendering?

I am working with React and I am trying to understand the life cycle. I am making the componentWillMount method to get the props I need before rendering. I need to know how to update state when loading a view.

All I'm trying to do is get a GET request to get a list of casino dealers. Basically, I skip 1 or 2 steps that are intended to display a list of dealers in the DOM

I will show what I do with my code and after that I will explain what I want

Part of the action

getDealerActions.js

 class GetDealersActions { constructor () { this.generateActions('dealerDataSuccess', 'dealerDataFail'); } getDealers (data) { const that = this; that.dispatch(); axios.get('someroute/get-dealers/get-dealers') .then(function success (response) { that.actions.dealerDataSuccess({...response.data}); }) } }; 

then we go to the stores

getDealersStore.js

 class GetDealersStore { constructor () { this.state = { dealerData : null, }; } @bind(GetDealersActions.dealerDataSuccess) dealerDataSuccess (data) { this.setState({ dealerData : data, }); console.log(this.state.dealerData); } } 

in this case, that console.log(this.state.dealerData); returns something like this, which is exactly what I need

 Object {dealersData: Array[3]} 

problems are part of it, honestly, because I don’t know how to process the data here.

 @connectToStores export default class Dealers extends Component { static contextTypes = { router : React.PropTypes.func, } constructor (props) { super(props); this.state = {} } static getStores () { return [ GetDealersStore ]; } static getPropsFromStores () { return GetDealersStore.getState(); } componentWillMount () { console.log('@@@', this.props); GetDealersActions.getDealers(); } render () { console.log('>>>', this.props); let content; if (this.state.dealerData) { content = this.state.dealerData.map((item) => { return <div key={item.CardId}>{item}</div>; }); } else { content = <div>Loading . . .</div>; } return ( <div> <div>{content}</div> </div> ); } } 

all i get here is <div>{content}</div> is Loading . . . Loading . . . because this.state fits as Object {}

The strange situation that I get here is that this view is executed twice, the first time is rendering, and console.log('>>>', this.props); returns this >>> Object {params: Object, query: Object} , and the second time it displays, it starts this >>> Object {params: Object, query: Object, dealerData: Object} , which is what I need.

So why is componentWillMount waiting for a rendering method to get fired?

+4
source share
1 answer

This is not strange. componentWillMount will fire before rendering, and in the first pass, you call an action to get dealers GetDealersActions.getDealers(); , which is basically an async command. Since it is asynchronous, the component will be displayed once before it receives the data, and then again after the store publishes the changed event, which will restart the rendering.

Here is an example of the sequence of actions occurring in your example:

  • componentWillMount calls the getDealers command (which is asynchronous)
  • initial render with default state
  • Async operation completed in action creator and repository installed with dealer data
  • the store publishes a changed event that re-starts rendering
  • second render is called with dealer data in component state.

The problem is that React will run its lifecycle methods in a specific sequence, without worrying about calling any async method. Thus, basically you have no way to stop rendering just because you called the command to get dealers . This is a react (or function) limitation that occurs in conjunction with asynchronous programming, and you should accept it as it is.

If you agree that React will render twice, you can use it to your advantage, so first visualize, you can simply show the loading indicator (for example, a spinning wheel), and when the data loads, you simply display it in the second render .

However, if you are unsure and still want to avoid double rendering in the initial load, you can prefetch the data before mounting the application component, which will ensure that the source data is loaded into the storage before rendering first, which would mean that you would not need to call getDealers in componentWillMount , because the data was already in storage on the first render .

As a reminder, double rendering is not a significant performance issue, as it would be in Angular.js or Ember.js, since React is very efficient at manipulating the DOM, but it can lead to some UX problems if not handled properly.

+6
source

Source: https://habr.com/ru/post/1233565/


All Articles