ComponentWillMount and ComponentDidMount not synced - reactjs

I am making a react application. I need to make an ajax call to fetch the data from server and populate this data in the rows of my component's table. I do my ajax call in componentWillMount and store the response in the state. Now my render fetched this state and populates it. I have a few questions though:
Am I doing it right to place ajax in componentWillMount?
My componentDidMount doesn't get the value of state which get's set in componentWillMount. This means the async is not complete while componentDidMount is trying to access it. How to solve this? setting async:false is really a bad option.
What all thing can be used in componentWillMount?

Yes, componentWillMount is called once before the render. This is the place to fetch data.
Probably when the component finished rendering, the componentDidMount called although the async operation didn't finished yet, therefore you get empty result.
You can use componentWillUpdate
componentWillUpdate() is invoked immediately before rendering when new
props or state are being received. Use this as an opportunity to
perform preparation before an update occurs. This method is not called
for the initial render.
Or shouldComponentUpdate,
shouldComponentUpdate() is invoked before rendering when new props
or state are being received. Defaults to true. This method is not
called for the initial render or when forceUpdate() is used.
It's a broad question, basically fetching data from actions, calling api's etc.
More info in docs

Am I doing it right to place ajax in componentWillMount?
The recommend approach is to place your initial network requests that modify state inside of componentDidMount, because in theory your ajax request could come back prior to React completing the mounting process which might lead to your state getting overwritten.
However, in practise people use both as the above scenario should never happen.
My componentDidMount doesn't get the value of state which get's set in
componentWillMount. This means the async is not complete while
componentDidMount is trying to access it.
That is the correct behaviour.
How to solve this? setting
async:false is really a bad option.
If you stop it then it's no longer async.
The best practise here would be to show a loading indicator:
add a loading property to state
set it to true just above your fetch request
inside .then and .catch set loading to false
inside render check if your data has arrived - if not display the loading indicator
If you don't want to show anything until your request comes back
You can return null inside of render which will prevent your component from being added to the DOM. You can then combine this with a flag state property to make sure the component gets mounted once your request comes back, i.e. something like this:
render() {
if (!this.state.initialRequestHasCompleted) return (null);
return (
<div>
...
</div>
);
}
What all thing can be used in componentWillMount?
What is the purpose of having functions like componentWillMount in React.js?

Related

Is componentDidMount triggered everytime I set state somewhere in the class?

I would like to know if componentDidMount gets triggered every time I setState(anywhere in the class)?
Second, I am calling a function fetchData inside componentDidMount, and fetchData is a database listener so it listens for changes in Firestore database. How is that called every time if I call it from componentDidMount?
The componentDidMount is called when the component is first added to the DOM (or render tree when on native), not when that component is subsequently updated/rerendered.
From the React docs on state and lifecycle:
The componentDidMount() method runs after the component output has been rendered to the DOM. This is a good place to set up a timer...
And the documentation on Component.componentDidMount:
componentDidMount() is invoked immediately after a component is mounted (inserted into the tree). Initialization that requires DOM nodes should go here. If you need to load data from a remote endpoint, this is a good place to instantiate the network request.
Setting state merely causes the component to be rerendered.

How to make sure API call receive data before react component initial render?

The app is a single page app, the initial render is throwing error since its rendering undefine variable.
My best guess would be invoked API call in getDerivedStateFromProps(props, state) but the doc said "If you need to perform a side effect (for example, data fetching or an animation) in response to a change in props, use componentDidUpdate lifecycle instead."
The solution I am always using is:
set in your component state a variable 'isLoading' with an initial value of true.
if you call the api only once, do it in your async ComponentDidMount, and once the api call completes, set isLoading to false
in render check the variable. If true, display a spinner or a 'loading' message. If false display whatever you need in your component
if the api is called periodically or upon an event, set the state variable to false every time you call the api and clear it when it is done

Will componentWillMount run again if component is re-rendered because of parent component?

Will componentWillMount run again if component is re-rendered because of parent component?
No, componentWillMount is called only once.
Also, componentDidMount is called only once.
componentDidUpdate is called on every re-render.
To correctly understand about the react lifecycle methods you can go through this link.
https://engineering.musefind.com/react-lifecycle-methods-how-and-when-to-use-them-2111a1b692b1
The short answer is NO
It's called once right before your component is about to be rendered to the DOM.
The long answer is:
componentWillMount
Your component is going to appear on the screen very shortly. That chunky render function, with all its beautifully off-putting JSX, is about to be called.
Most Common Use Case: App configuration in your root component.
Can call setState: Yes, but don't. Use the default state instead.
componentDidMount
Here is where you load in your data. ComponentDidMount is also where you can do all the fun things you couldn’t do when there was no component to play with. Basically, here you want to do all the setup you couldn’t do without a DOM, and start getting all the data you need. Most Common Use Case: Starting AJAX calls to load in data for your component.
componentWillReceiveProps
Perhaps some data that was loaded in by a parent component’s componentDidMount finally arrived and is being passed down. Before our component does anything with the new props, componentWillReceiveProps is called, with the next props as the argument.
shouldComponentUpdate
shouldComponentUpdate should always return a boolean — an answer to the question, “should I re-render?” Yes, little component, you should. The default is that it always returns true. It's an awesome place to improve performance.
componentWillUpdate
Most Common Use Case: Used instead of componentWillReceiveProps on a component that also has shouldComponentUpdate (but no access to previous props). It’s basically the same as componentWillReceiveProps, except you are not allowed to call this.setState.
componentDidUpdate
Here we can do the same stuff we did in componentDidMount — reset our masonry layout, redraw our canvas, etc. Basically, we use it when it's all said and done, but we don’t want to waste time to redraw the canvas every time it updates. Most Common Use Case: Updating the DOM in response to prop or state changes.
componentWillUnmount
Here you can cancel any outgoing network requests, or remove all event listeners associated with the component. Basically, clean up anything to do that solely involves the component in question — when it’s gone, it should be completely gone.

why we prefer to write header or api request or ajax code in componentDidMount not in componentWillMount

why we prefer to write header or api request or ajax code in componentDidMount not in componentWillMount.
need simple and clear difference with example
You should use componentDidMount() because you need the component to be rendered in order to populate it with the data that you're fetching from the API.
componentWillMount(){
//Fetch API and set the State
}
render(){
return(<div>{this.state.myData}</div>)
}
When componentWillMount() fires up the <div> hasn't been rendered yet (does not exist at the moment in the DOM).
When using componentDidMount() in the other hand. The render method runs first creating the <div> element in the DOM, after that then componentDidMount() runs, fetching the data, you set your state and that creates a re-render of the component. That's why we use componentDidMount() to fetch data from the API. you can find more information here.
caveat: You should validate the state so you don't get undefined the first time the component is render (without the data from the API).
edgaromar90 the same case with constructor also. we usually set temporary state in constructor and constructor invokes before the initial render. both constuctor and willMount invokes before initial render, then why we are not using in componentWillMount

Reactjs- countering undefined error in referencing state sub elements in render methods

I run frequently into problem while using React in a specific way.
I have a hierarchy of components. The application state lives in the common owner uppermost component. I set initial state with empty objects, or arrays whatever in getInitialState. I fetch data via ajax with calling a method of this state owner uppermost component in this component's componentDidMount. But whether I use the state set in the success callback of the ajax call in this same component, or in sub components, by passing the state to them via props, I almost always get a variable can't find or something undefined sort of errors.
Thinking conceptually, the render method invoked when I mount the components, so it will not find data in the variables embedded in it. But we have getInitialState. This seems ok but what if the nested objects are being used in the render methods. States in the getInitialState are just empty objects, so references to the to be sub elements are undefined.
Even using componentWillMount does not work. Only way seems having initial states and not to reference any undefined sub elements of those in the render. However it seems necessary in most cases. Is the issue related to this necessity I see being actually an anti-pattern.
I have found React very useful for me at first tutorials and simpler cases, but now I cannot make use of it efficiently.
How to counter this behaviour correctly and in the best practice possible?
FIRST SOLUTION:
The method I use is simply check is the state exists in the render function
render: function() {
var result = { this.state.field ?
this.state.field.embeddedfield ?
<div> this.state.field.embeddedfield </div>
: <div> Data are loading! </div>
: "" }
return {result};
}
SECOND SOLUTION
If you want your data to be ready before rendering you need to execute the first fetch outside :
$.ajax({...}).success(function(res) {
<MyView data={res} /> // render your function on success
});
See this : bind(this) not working on ajax success function
To answer about why componentWillMount won't work:Putting ajax call in componentWillMount won't work because it won't wait for your call to be fetched and cycle concurrency may also occurs.

Resources