Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React render() is being called before componentDidMount()

In my componentDidMount() I am making an API call to fetch some data, this call then sets a state object that I use in my render.

componentDidMount() {             const { actions } = this.props;              this.increase = this.increase.bind(this);              // api call from the saga             actions.surveyAnswersRequest();              // set breadcrumb             actions.setBreadcrumb([{ title: 'Score' }]);             actions.setTitle('Score');             this.increase();         } 

In my render function I pass some prop values onto the view file:

render() {         const { global, gallery, survey_answers, survey, survey_actual_answers } = this.props;          if (global.isFetching) {             return <Loading />;         }         return this.view({ gallery, survey_answers, survey, survey_actual_answers });     } 

The problem I am having is that the survey_actual_answers prop is not being set the first time that the page is loaded, however when I refresh the page the prop returns the data fine and the rest of the script will run. It's only the first time that it returns an empty array for that prop value.

This is how I have passed my props in:

Score.propTypes = {     actions: PropTypes.object.isRequired,     global: PropTypes.object.isRequired,     survey: PropTypes.object.isRequired,     survey_answers: PropTypes.object.isRequired,     gallery: PropTypes.object.isRequired,     survey_actual_answers: PropTypes.array.isRequired,     survey_score_system: PropTypes.array.isRequired,     survey_styles: PropTypes.object.isRequired,     survey_general_doc_data: PropTypes.object.isRequired };  function mapStateToProps(state, ownProps) {     return {         ...ownProps,         global: state.global,         gallery: state.gallery,         survey: state.survey,         survey_actual_answers: state.survey.survey_actual_answers,         survey_answers: state.survey.survey_answers,         survey_score_system: state.survey.survey_score_system,         survey_styles: state.survey.survey_styles,         survey_general_doc_data: state.survey.survey_general_doc_data,         isFetching: state.isFetching     }; }  function mapDispatchToProps(dispatch) {     return {         actions: bindActionCreators({             ...globalActions,             ...galleryActions,             ...surveyActions         }, dispatch)     }; } 

Does anyone know why this is happening? It's almost as if it's not calling componentDidMount at all.

like image 550
user3574492 Avatar asked Jul 26 '17 20:07

user3574492


People also ask

Is render called before componentDidMount?

If you will see carefully in the console panel, then it first logs “First this called” and then our initial state is defined and then render() method is called then componentDidMount() method is called and then newly fetched data is displayed in the component.

Is componentDidMount called after every render?

There is no call to ComponentDidMount. It is only called once after the initial render.

Which of the React lifecycle method is called before rendering?

getDerivedStateFromProps. The getDerivedStateFromProps() method is called right before rendering the element(s) in the DOM. This is the natural place to set the state object based on the initial props . It takes state as an argument, and returns an object with changes to the state .

What is called before render?

componentWillMount() This method is called just before a component mounts on the DOM or the render method is called. After this method, the component gets mounted. Note: You should not make API calls or any data changes using this. setstate in this method because it is called before the render method.


2 Answers

This is happening because of how React works fundamentally. React is supposed to feel fast, fluent and snappy; the application should never get clogged up with http requests or asynchronous code. The answer is to use the lifecycle methods to control the DOM.

What does it mean when a component mounts?

It might be helpful to understand some of the React vocabularies a little better. When a component is mounted it is being inserted into the DOM. This is when a constructor is called. componentWillMount is pretty much synonymous with a constructor and is invoked around the same time. componentDidMount will only be called once after the first render.

componentWillMount --> render --> componentDidMount

How is that different than rerendering or updating?

Now that the component is in the DOM, you want to change the data that is displayed. When calling setState or passing down new props from the parent component a component update will occur.

componentWillRecieveProps --> shouldComponentUpdate-->componentWillUpdate
-->render-->componentDidUpdate

It is also good to note that http requests are usually done in componentDidMount and componentDidUpdate since these are places that we can trigger a rerender with setState.

So how do I get the data before the render occurs?

Well, there are a couple of ways that people take care of this. The first one would be to set an initial state in your component that will ensure that if the data from the http request has not arrived yet, it will not break your application. It will use a default or empty state until the http request has finished.

I usually don't like to have a loading modal, but sometimes it is necessary. For instance, when a user logs in you don't want to take them to a protected area of your site until they are finished authenticating. What I try to do is use that loading modal when a user logs in to front load as much data as I possibly can without affecting the user experience.

You can also make a component appear as loading while not affecting the user experience on the rest of the site. One of my favorite examples is the Airbnb website. Notice that the majority of the site can be used, you can scroll, click links, but the area under 'experiences' is in a loading state. This is the correct way to use React and is the reason why setState and HTTP requests are done in componentDidMount/componentDidUpdate.

like image 115
EJ Mason Avatar answered Sep 28 '22 05:09

EJ Mason


Using setState in componentdidmount. This my code:

 async componentDidMount() {      danhSachMon = await this.getDanhSachMon();     danhSachMon=JSON.parse(danhSachMon);     this.setState(danhSachMon); }  render() {     return (         <View>             <FlatList                 data={danhSachMon}                 showsVerticalScrollIndicator={false}                 renderItem={({ item }) =>                     <View >                         <Text>{item.title}</Text>                     </View>                 }                 keyExtractor={(item, index) => index.toString()}             />         </View>     ) } 
like image 25
truong luu Avatar answered Sep 28 '22 05:09

truong luu