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).
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.
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.
This question is about internals for partial re-renderings with React-Redux.
To explain what I mean, I will first introduce a very crude technique for managing state without any state management libary.
The technique uses a a huge "AppState"-object that is owned by the top-level App-component.
Suppose that this AppState holds not only state-properties, but also several callbacks that mutate those state-properties.
Furthermore, suppose that we use props to pass down this AppState throughout the entire component hierarchy.
Thanks to the ES6-spread syntax, passing a huge number of props can be done without a lot of boilerplate code.
In the top-level App-component, it will look like this:
<ChildComponent {...this.state} />
In all other components, it will look like this:
<GrandChildComponent {...this.props} />
It is important to note that the ES6-spread syntax does not actually pass the AppState-object. Instead, it extracts all the AppState-properties and passes them as separate props.
Now we should distinguish between top-level properties and nested child-properties of the AppState:
If I mutate a top-level property of this AppState by calling setState, then the entire app will re-render (unless I use things like pure components).
However, if I change a nested child-property of this AppState, then nothing will happen because React does not notice the property change.
This leads to my final questions:
What is the render-performance of this crude approach in comparison to Redux?
How exactly does Redux handle "partial renderings", such that only some of the Components re-render after a state mutation?
If I mutate a top-level property of this AppState by calling setState, then the entire app will re-render (because everything depends on the AppState).
If you mutate and use pure components then nothing will render, you change state by creating a new state object.
However, if I mutate a nested child-property of this AppState, then nothing will happen because React does not notice the property change.
This is only true if you mutate and components are pure.
What is the render-performance of this crude approach in comparison to Redux?
Prop drilling will re render the entire tree but branches that use state that didn't change won't re render if they are pure. Prop drilling is bad for maintenance because if you need to refactor grand child state logic you may need to refactor the whole tree or branch. But from a performance point it would not take a big hit provided that you use pure components and are careful when passing callbacks and not re creating them on every render (see useCallback).
How exactly does Redux handle "partial renderings", such that only some of the Components re-render after a state mutation?
React-redux useSelector or connect mapStateToProps are always called every time dispatch changed state and before rendering.
If the result is different than last result then react-redux will trigger render of the component. If the component gets props then a render could also be triggered because props change and mapstate/selector will be executed.
A connected component will observe state and render when the result of mapState or selector has changed. An example app with logs showing what react-redux will execute can be found here
For state management, you don't necessarily have to use Redux, if your use cases are small, maybe React Hook would be perfect for you.
For React rerendering matter, what I know is there are several strategies (useMemo, PureComponents) provided by React for managing and improve the performance. It really depends on how you manage your components.
One example is using PureComponent, even if you have a large state in your top-level app.js, if you manage the child components properly, they will not re-render if their receiving props haven't changed.
I would like to know how long it takes my app to become "ready" for the user to interact with it. The timeline of the app loading includes the following:
DOM load.
Initial React render.
HTTP calls triggered from various componentDidMount()s
HTTP calls return. Redux state is updated with HTTP responses.
React renders with new values from HTTP responses.
All initial loading is complete. The user is ready to interact with the app.
At the end of this process, I'd like to fire a tracking event to record the value of window.performance.now().
I'm not sure what the best way to do this is. React's component system does a good job of decoupling various parts of the UI. In this case, it, unfortunately, means that I'm not going to have one easy place to check to know "has everything been rendered with the new data".
Things I've tried or considered:
Look for a React lifecycle hook that tells me if any child is updating. Something like componentOrAnyChildDidUpdate(). I don't think this exists, and it may be counter to the React philosophy.
Hack together an anyChildDidUpdate() lifecycle hook via context and making every component in my app either subclass a helper abstract base class or be wrapped in a higher-order component. This seems bad because context is an experimental API.
Subscribe to the Redux state via store.subscribe(). Update the Redux state to have an explicit record of whether all the HTTP calls have returned. Once all the HTTP calls have returned, and React is finished re-rendering, then I know to fire the tracking callback. The problem is knowing when React is finished re-rendering. It would work if my store.subscribe() the callback was guaranteed to be executed synchronously after react-redux's callback. But that is not the case.
Is there a good way to do this in React?
I'm afraid there is not a universally good way to do this in React, this is "logic" that is related with the structure of your application.
I wanted to display a loader when navigating from one page to another in Single Page Application(SPA) written in react and I faced a similar problem not knowing when to stop displaying it and if all the components in the new page have completed their API calls/renders.
The way I resolved it was:
1) I removed all my API calls from inside my components.
2) Create a Page component to wrap all the components included in that page(invoked by your react router).
3) Perform all requests required for your components simultaneously on navigation(in my case while displaying the loader). For each request that completes, create a promise and inside it create your component dynamically using React.createElement. Pass to the component created the request response and the promise handler as props.
4) Resolve the promise in your component's componentDidMount.
5) Once all the promises are resolved you know the "page" is ready and you can record the value of window.performance.now().
It is hard to provide a minimal code example without a lot of out of context code since this code is spread across the application.
There's more than one way to do what you're asking - but off the top of my head I would do the following:
• Create a perf reducer and call performance.now() right before I make the redux store and add the value to the initial state.
{ perf: { start: '...', end: '...' } }
• Track loading status of initial HTTP requests in a loaded reducer.
{ loaded: { request1: false, request2: false, request3: false } }
• Connect top level component to loaded reducer and check if all requests are complete in componentDidUpdate. If true add end value to perf reducer.
import React from 'react';
import { connect } from 'react-redux';
class App extends React.Component {
componentDidUpdate(prevProps) {
if (!prevProps.loadingComplete && this.props.loadingComplete) {
this.props.updatePerf(performance.now());
}
}
}
const mapStateToProps = state => ({
loadingComplete: state.loaded.every(item => item),
});
const mapDispatchToProps = dispatch => ({
updatePerf(time) {
dispatch({ type: 'SET_ENDING_PERF', payload: time });
},
});
export default connect(mapStateToProps, mapDispatchToProps)(App);
In our project, we use redux and a couple of actions - trigger, request, success, error.
"Trigger" calls request and throw loading: true into our "smart" component
"Request" fetch data and throw them into Success/Error
"Success", tells us that everything is fine and data loaded and throw { loading: false, data }
On success/error, we always know that is happening with our application
And of course you can use componentWillReceiveProps(nextProps) {} and check loading flag and data in your component
You can try to use react-addons-perf
That's how I benchmark my apps usually:
Basically you want to start measuring when your component starts updating and stop the measurement after the lifecycle method componentDidUpdate().
import Perf from 'react-addons-perf'
componentWillMount() {
window.performance.mark('My app');
}
componentDidMount() {
console.log(window.performance.now('My app'));
Perf.start()
// ... do your HTTP requests
}
componentDidUpdate() {
Perf.stop();
Perf.printInclusive();
}
Like that you will track your component initial render + your component updates.
Hope it helps
Two steps to achieve this.
Track all HTTP-requests via actions
Simple counter in redux state would be enough, that increments on start of request and decrements on success or fail (all via appropriate actions).
No window.dirty.stuff here in front of Dan Abramov.
Track all connected components
componentDidUpdate method indicates that all children finished rendering. This can be achieved without much boilerplate with recompose's lifecycle HOC. Right place to start tracking re-render might be sCU method or just cWRP if you use recomposes shouldUpdate or reselect already - since we won't track components that didn't update.
Note that all is assuming idiomatic react/redux app, no tricky side-effects or animations. For example, if some child component somewhere deep in the hierarchy fires its own AJAX request, say on cDM, not via redux action. This way you have to track them too, BUT no one can be sure if they imply any re-renders.
Tracking such behaviors is still possible, just might require more effort.
from a design POV, in my opinion being ready or not is a user presentation property and so should be handled by react components alone.
for example, you may later decide to allow the user to interact with some part of your UI while some other parts are still loading, or you may decide that some components should allow the user to interact before the data model is ready, etc ... in other words, it's a (react) component responsability to tell if/when it's ready or not and nobody else.
That is, all 'waitable' components could expose an onLoad-like prop to be passed up the react tree; the root component would then coordinate the result by changing the tree down stream accordingly by propagating the appropriate props down to leaves.
This could be implemented by writing a mixin/high order component to incapsulate the "readyness update" logic.
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.