In React componentDidMount is used during the mounting phase, for example, one can setState and wrap it in componentDidMount. But, one can use setState directly and then render the component.
In which cases should I prefer componentDidMount for a mounting phase?
It's useful for several things:
Starting ajax
As the documentation says, doing subscriptions to things (for instance, if the component receives updates in some way that isn't handled by its parent component, such as a stream of events from a web socket)
Basically any time you want to kick off a process when the component is first mounted.
The classic example is a component that loads something via ajax. It goes like this:
In the component's constructor, you create its default state saying it's loading something.
In componentDidMount, you start the ajax call that loads the thing.
When (if) the ajax call succeeds, you use the data from the call to update state
You write the render method so that it knows about the loading state and shows either loading or the thing that it loaded (or a loading error) appropriately.
(There are situations where you don't want to do that, where you want to load the thing in the parent component instead and only create the component that shows it when you have the thing. But other times doing it directly in the component isn't uncommon, and it makes a useful example.)
componentDidMount - When you want to execute the functionality only once when component is created.It will be executed only once by react.
Related
So I know somethings about vue's life cycle hooks but for some of them I can't think of any real world use case or example that should be done in them and I think it might help me to better understand them by finding out their use case.
here is what I know and don't know about them:
Creation Hooks
beforeCreate(): events and lifecycle have been initialized but data has not been made reactive --- use case ??
created(): you have access to data and events that are reactive but templates and virtual DOM have not yet been mounted or rendered --- use case: API calls
Mounting Hooks
beforeMount(): runs before the initial render --- use case ??
mounted(): you have access to the reactive component, templates and rendered DOM --- use case: modifying the DOM
Updating Hooks
beforeUpdate(): runs after data changes and before the DOM is re-rendered --- use case ??
updated(): runs after data changes and the DOM is re-rendered --- use case ??
Destruction Hooks
beforeDestroy(): runs before tear down --- use case: clean ups to avoid memory leak
destroyed(): runs after tear down --- use case ??
Thanks in advance to anyone helping me to understand these concepts better ;)
According to official VueJS website:
Each Vue instance goes through a series of initialization steps when it’s created - for example, it needs to set up data observation, compile the template, mount the instance to the DOM, and update the DOM when data changes. Along the way, it also runs functions called lifecycle hooks, giving users the opportunity to add their own code at specific stages.
Having that in mind, we have:
beforeCreate
The beforeCreate hook runs at the very initialization of your component. data has not been made reactive, and events have not been set up yet.
Usage
Using the beforeCreate hook is useful when you need some sort of logic/API call that does not need to be assigned to data. Because if we were to assign something to data now, it would be lost once the state was initialized.
created
You are able to access reactive data and events that are active with the created hook. Templates and Virtual DOM have not yet been mounted or rendered.
Usage
Using the created method is useful when dealing with reading/writing the reactive data. For example, if you want to make an API call and then store that value, this is the place to do it.
The above are famously called as creation hooks, as opposed to mounting hooks.
Mounting hooks are often the most used hooks. They allow you to access your component immediately before and after the first render. They do not, however, run during server-side rendering.
beforeMount
The beforeMount hook runs right before the initial render happens and after the template or render functions have been compiled.
Usage
This is the last step you should perform your API calls before it’s unnecessary late in the process because it’s right after created — they have access to the same component variables.
mounted
In the mounted hook, you will have full access to the reactive component, templates, and rendered DOM (via this.$el).
Usage
Use mounted for modifying the DOM—particularly when integrating non-Vue libraries.
There also some hooks, which are called updating hooks.
Updating hooks are called whenever a reactive property used by your component changes or something else causes it to re-render. They allow you to hook into the watch-compute-render cycle for your component.
Use updating hooks if you need to know when your component re-renders, perhaps for debugging or profiling.
There are:
beforeUpdate
The beforeUpdate hook runs after data changes on your component and the update cycle begins, right before the DOM is patched and re-rendered.
Usage
Use beforeUpdate if you need to get the new state of any reactive data on your component before it actually gets rendered.
updated
The updated hook runs after data changes on your component and the DOM re-renders.
Usage
Use updated if you need to access the DOM after a property change
And last but not least, there are destruction hooks.
Destruction hooks allow you to perform actions when your component is destroyed, such as cleanup or analytics sending. They fire when your component is being torn down and removed from the DOM.
There are:
destroyed
By the time you reach the destroyed hook, there’s practically nothing left on your component. Everything that was attached to it has been destroyed.
Usage
Use destroyed if you need do any last-minute cleanup or inform a remote server that the component was destroyed
beforeDestroy
beforeDestroy is fired right before teardown. Your component will still be fully present and functional.
Usage
Use beforeDestroy if you need to clean-up events or reactive subscriptions.
This is the stage where you can do resource management, delete variables and clean up the component.
Keep in mind that these are the main lifecycle hooks and there are some other minor ones such as activated and deactivated that you can look into.
Here is a link that might help you further down the line.
I have always made API's request in ComponentDidMount lifecycle and called setState in the callback. But while digging deep I happened to find out We should not call setState in this lifecycle as it triggers render method again and React also doesn't recommend that.
Then in that case where exactly we should make that request and call setState to use result after that?
You should absolutely make an API call in componentDidMount. What is not recommended is to re-render a big component, instead what you should do is break your UI into small logical components and only re-render only what is needed , not a whole. For example, you have a big component named HomeComponent which has 3 small components called NavComponent, BodyComponent and FooterComponent. You should NOT be calling the API from the componentDidMount of the HomeComponent since calling setState from HomeComponent will re-render all the small components inside HomeComponent, which is not necessary since you know that the navbar or footer is not needed to be re-rendered. Rather from the BodyComponent, because only the body part needs to be re-rendered since its state has changed. So you should be calling the API from the componentDidMount of the BodyComponent, that way you re-render only whats needed.
#Shababb Karim is right but if i were to implement API calls in my project i would add a state management library. Redux is a great way to implement a global state to the app where you can set data from said API. All components that need that data can be attached to the Redux state to get it.
Redux can be a bit of overhead in smaller projects though. In this case there are other options like Flux (although i like Redux more).
Firing server call to fetch data in componentWillMount life cycle method a bad practice?
And why it is better to use componentDidMount.
UPDATE: componentWillMount will soon be deprecated.
To cite #Dan Abramov
In future versions of React we expect that componentWillMount will fire more than once in some cases, so you should use componentDidMount for network requests.
Read more here.
UPDATE - may / 2018
There is a new feature for react in a working progress called async rendering.
As of react v16.3.2 these methods are not "safe" to use:
componentWillMount
componentWillReceiveProps
componentWillUpdate
you can read more about it in the docs.
As a general rule don't use componentWillMount at all (if you use the es6 class syntax). use the constructor method instead.
This life-cycle method is good for a sync state initialization.
componentDidMount in the other hand is good for async state manipulation.
Why?
Well, when you do an async request in the constructor / componentWillMount you do it before render gets called, by the time the async operation has finished the render method most probably already finished and no point to set the "initial state" at this stage is it?.
I'm not sure this is your case here, but most of the cases that developers wants to initiate state asynchronously in componentWillMount is to avoid a second render call. but you can't avoid it can you, like mentioned above, render will fire anyway before the async operation will finish.
So, the best time to call an async operation is after a render has called and the component mounted (you could mount null or an empty <div/>) and then fetch your data, set the state and make it re-render respectively.
componentDidMount is the best place to put calls to fetch data, for two reasons:
Using componentDidMount makes it clear that data won’t be loaded until after the initial render. You need to setup initial state properly, so you don’t get undefined state that causes errors.
If you need to render your app on the server, componentWillMount will be called twice(on the server and again on the client), which is probably not what you want. Putting the data loading code in componentDidMount will ensure that data is only fetched from the client. Generally, you should not add side effects to componentWillMount.
Component Mounting life cycle is
constructor()
componentWillMount() /UNSAFE_componentWillMount()(react 16)
render()
componentDidMount()
Constructor and componentWillMount both call before render() call which is responsible for page rendering.
Here State initialized is done in Constructor and api are called in componentDidMount because of async calls.
ComponentWillMount was good to initialized state before ES6 when constructor was not there. But now ComponentWillMount is good for nothing and react team is thinking it after react 17.
In addition to above, react have moved to react fiber architecture, to avoid unnecessary re-rendering and improve performance, react has decided to move away from componentWillMount, componentWillReciveProps and componentWillUpdate methods.
The way I understand it, one of the biggest reasons has to do with setting up the right expectations for the developers reading the code.
If we use componentWillMount it's tempting to think that the fetch have time to happen, then the component "did" mount, and then the first render will happen. But that it not the case. If we do an async call (like an API call with Promises), the component will actually run render before the fetch can return and set the component state (or change the Redux state, or what ever).
If we instead use componentDidMount, then it's clear that the component will render at least once before you get back any data (because the component already did mount). So, by extension, it's also clear that we have to handle the initial state in a way so that the component doesn't break on the first ("empty") render.
It is my understanding that you are not supposed to change states in the render function cause that would cause and infinite re render or the component.
This makes perfect sense, but I find myself in a particular situation. I am building an offline application and I am using an offline storage system to retrieve data. Now, whenever a method is called to get certain data, cache is checked, if it is not expired the component will be able to access the data and therefore nothing happens, but if it is expired there is a call to the API, the data is updated and the interested components re-rendered.
These methods will change the state of the component the first time they are called because they are going to the API grabbing the new data and re-rendering, and then they will not change the state anymore because the data will already be in cache.
Now, I could call these methods in component will mount, and that is what I am doing now, but if I am forced to re call them, I need to unmount and remount the components. Is this the only possible way of doing this?
Thanks!
Well the first step is understanding that state management and rendering needs to be decoupled which you got already.
Now what you can do is consider your external state/cache element as an observable object (ie. I want to do something like observableObject.listen('change', onChangeHandler); you can use EventsEmitter from the events library). You do that listening on componentDidMount and clean up in componentWillUnmout. That onChangeHandler is very simple: this.setState({ value: observableObject.value }) which will trigger a component re-render which should be a pure function that outputs DOM nodes depending on props being passed and it's own state.
This means that your logic of checking if the cache is invalid is not on a per request of the value (inside rendering) but rather think of the object as self contained. It regularly checks if itself needs to notify its listeners that it changed. Since JS does not do parallel execution you don't have to deal with threads and synchronization. You know that at the point in time your render function executes it will have the latest value. If after rendering the logic that checks for cache executes and it sees that it needs to be updated it simply notifies as said earlier its listeners and that makes your component re-render because your onChangeHandler changed the state.
Hope I helped.
I saw this line as an answer to another question on here:
"componentWillMount should be componentDidMount, or else you'll leak event emitters in node."
and I don't really understand it. Can someone explain with more detail?
More info:
Building a react application with flux, as part of the initial render, a child component computes some data. Ideally, after this data is computed, I would like to call an action that updates the store's state with a portion of this new data.
Normally, updating the store's state emits a change event that causes a re-render. However, because the change listener isn't being added until componentDidMount (rather than in componentWillMount), my top level component isn't able to listen for the change that occurs during the initial render and initiate a re-render.
If I move the addChangeListener to componentWillMount that would seem to fix this issue, but the above quote suggests that this is a bad idea?
I think the prevailing wisdom that listeners should be set in componentDidMount because it prevents problems in isomorphic applications is a mistake. I think in 98% of cases for non-isomorphic applications setting listeners in either componentWillMount and componentDidMount will work the same way, but it is conceptually wrong and in the 2% of cases (such as the example given in the original question) it will do the wrong thing.
There are git issue discussions and comments in the React source code suggesting that it would be preferred that componentWillMount wasn't called on the server at all, but if it isn't then problems are created in the checksum test comparing the server prerender to the client initial render. Having componentWillMount on the server means that it isn't executed as part of the component lifecycle in this case, but this is being used as an excuse to not count it as part of the lifecycle in any case.
In fact, componentWillMount is exactly the right place to register listeners if you are not creating an isomorphic application. If you are creating an isomorphic application then you have to make some compromises due to the checksum/lifecycle issue not being ideal in this case (maybe just testing for the server environment and then not registering listeners?).
In non-isomorphic applications adding listeners in componentWillMount can save unnecessary re-renders in some cases and will register them in document order. The advantage of document order is that if you have a way to flush pending events as components are re-rendered (for example, takeRecords on a MutationObserver) then you can ensure the document is re-rendered top down instead of bottom up, converting the rendering complexity to linear from polynomial.
Additionally, there is no danger period between the initial render and when the listener is registered where the Store can change without triggering a render, causing the view to be out of sync with the Store (the example problem given in the original question). If the listener is registered in componentDidMount you either need to make sure the Store isn't changed in componentDidMount calls in children, or else force a re-render/re-sync after registering the listener, which if done in componentDidMount is done in reverse document order which may be polynomial complexity (depending on how/if the React setStates are aggregated).
Is hard to understand what that quote means without more context. What I can tell you is that there are huge differences between the two of those methods.
On one hand, componentWillMount is called before the component is actually added to the DOM. This is the last chance you have to update component's state and get it rendered before the component is rendered by the browser.
On the other hand, componentDidMount is called once the component has been attached to the DOM (the real one).
What you need really depends on your use case. In general, componentDidMount is used to integrate with other libraries (like jQuery), it provides a way to modify the HTML rendered by the component.
I suggest you to read these links:
https://facebook.github.io/react/docs/component-specs.html#mounting-componentwillmount
https://facebook.github.io/react/docs/component-specs.html#mounting-componentdidmount
https://facebook.github.io/react/tips/use-react-with-other-libraries.html