After reading one of Alligator.io posts about Vue that was saying that mounted lifecycle is a bad place to use http get. I was wondering if there are any guidelines to how properly get data from API in Vue.js?
I`m prefer call API in created hook. Quote from alligator.io:
In the created hook, you will be able to access reactive data and events are active. Templates and Virtual DOM have not yet been mounted or rendered.
So you easy can access to data to parse and save response from a server if you need.
The created() lifecycle hooks fullfills all requirements for fetching and processing API data.
However the official Vue documentation uses the mounted() lifecycle hook in example code for integration API calls with axios:
https://v2.vuejs.org/v2/cookbook/using-axios-to-consume-apis.html
Both lifecycle hooks mounted() and created() are widely used for fetching API data and considered as good practice.
The answers make sense but if we use the mounted() hook to call the API's, assuming that the DOM is rendered. If we update a state here in mounted() will it trigger another render?
I am sure that in created() hook the DOM is not yet mounted. So, I might go with created().
Answer
The best hook for this are mounted and beforeMounted expect some edge cases
Why?
Vue can cache the components and created hook doesn't give any guarantee that Vue will apply it on the next mount. Sometimes you can find that your component has been saved the state. So if you don't see a component, it doesn't mean that it haven't been created.
SSR: If you want to get a universal component its won't be valid to place any fetch methods to created hook. You will just receive an error while ssr rendering. And mounted hooks work only on the client side
If you care about performance and time, please don't. Fetch will be done after created and mounted hooks anyway, because hooks are synchronous and fetch is not. Also time between created and beforeMounted is very very short.
You can place it to created if you don't plan the ssr and if you know how Vue works and you really need to place it to created hook.
Related
The official React docs says that you should fetch data from server in componentDidMount lifecycle method.
It could sound a bit weird that in case when your component need some data (which is pretty often) you should always wait for initial rendering, including slow DOM api manipulations for the component and its children. It provides unreasonable delay in sending the request to server.
How could you explain why it is a good decision for React team not to implement a special lyfecycle method like componentFetchInitialData (which is invoked at the beginning) for initial data fetching?
The question from the interview that made me confused
We are making an axios call that pulls in a gigantic object which is used to render a very lengthy UI using Bootstrap Vue.
The issue is that the UI continues to be rendered well after the axios call has been received.
Is there a way to check if everything is done rendering in Vue? The mounted hook does not work here.
More context:
The Laravel Debugbar gives me the best feedback here. When #6 AJAX is done, I know that the UI is done rendering. But how I can sync Laraven's debugbar with Vue's hooks?
Maybe to try with this.$nextTick inside updated hook
There is another lifecycle hook in vue beside mounted
The updated lifecycle hook is fired everytime a component reactive property changes and the virtual dom is updated.
To react to virtual dom changes inside the updated hook you can use nextTick()
In an interview, an interviewer asked me that where should you make API-hits in a simple react application? Meaning in which life-cycle method in a Class-Component. I knew the answer to be ComponentDidMount - because it is the first life-cycle method where we get complete rendered dom meaning dom is now ready!
Then he asked, but why NOT in comonentDidUpdate?
Now, I told him what I had read somewhere, I don't know the exact answer of this -- except ComponentDidMount runs first, so make it there.
Now, can someone tell me if my answer was correct? Or should we make API-hits in ComponentDidUpdate()?
I am confused. Kindly, someone explain with reasoning? Thanks in Advance!
It depends on when you want to call the API:
If an API call is done only once then do componentDidMount
If after render based on some state, you want to fetch data again then do it in componentDidUpdate
EDIT:
Same scenarios can be handled within functional components using useEffect hook as follows:
1- Only runs the first time when the components render same as componentDidMount:
useEffect(() => {
// Run only once when the component renders
}, []); // Pass empty array as dependencies
2- Run every time when component renders either by props change or by local state change same as componentDidUpdate without comparing previous and current props:
useEffect(() => {
// Run every time the component re-renders including the first time
}); // Do NOT pass array dependencies
3- Run only when particular props change, same as componentDidUpdate but with props comparison:
useEffect(() => {
// Run only when the component prop1 and prop2 changes
}, [prop1, prop2]); // Pass props as array dependencies
Reference: Using the Effect Hook
Lets take an example scenario.
You have a profile page and it has a text box which allows you to update tags.
You do a fetch for the whole profile in the componentDidMount to get all the details and show the content.
And then componentDidUpdate will have to be used for something like the update on tags, lets say you do a fetch to get tags based on the user input for every 3 letters the user type. then you use componenDidUpdate to check the state and do the call.
If you think of the same in functional components we'll have to use useEffect.
useEffect(()=>{},[]);
See the array of dependecies, if you pass an empty array it would act similar to componentDidMount.
And the componentDidUpdate
useEffect(()=>{},[tagText]);
Here the effect will run only when a change it done to the tagText, but the componenDidUpdate would be different as you will have to compare the previous state and decide whether the text is updated.
According the Official React Documentation (Link):
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.
This method is a good place to set up any subscriptions. If you do
that, don’t forget to unsubscribe in componentWillUnmount().
componentDidUpdate()
componentDidUpdate() is invoked immediately after updating occurs.
This method is not called for the initial render.
Use this as an opportunity to operate on the DOM when the component
has been updated. This is also a good place to do network requests as
long as you compare the current props to previous props (e.g. a
network request may not be necessary if the props have not changed).
Check out this link for a complete big picture. This will be handy while learning react.
I am still learning React and I apologize if this is a stupid question. I am currently planning about the architecture of my simple App.
I am using Next.js for this project
I have a component that calls the third party API for data every 5 seconds. The data is shared among all pages in the app.
If the component that is fetching the data is not on the main/home page. Are there anyways for homepage to get the data it needs from another page?
For example [Below are all pages]
index.js // Plain simple page that displays current weather and top music
http://localhost:3000/
weatherforecast.js //Using componentDidMount every 5 seconds to fetch Weather Data
http://localhost:3000/weatherforecast
musicplaylist.js //Using componentDidMount every 5 seconds to fetch Weather
http://localhost:3000/musicplaylist
The data shown in homepage has to be refreshed every 5 seconds if there are changes to the following data in weatherforecast.js and musicplaylist.js
I had this in mind but I have a feeling that it's not the right way to do it.
In the Homepage.js, include WeatherForecast and MusicPlaylist components to fetch the data. If this is the case, it seems like I am repeating the same principle in every page.
I found out about Redux which store states as a global object. But how does the state know when to update. But before we getting to state, I am still not sure if components on another page can fetch the data without the user accessing the page.
Thanks for reading this question.
For a pure React solution, you need to utilize other lifecycle methods available for React. componentDidMount is a good spot for making API requests, so you're in the right place to start. However, componentDidMount occurs only once, right after the componentWillMount and after the DOM is ready with a complete render of the component. Setting your API call to run at a set interval will not trigger a rerender of the component, no any of it's sub components. Instead, use componentWillRecieveProps to add your interval request logic. After each interval completes, run setState with the new data from the request to update the default state defined in your constructor. As a bonus step to improve performace, follow up with function that returns a bool in componentShouldUpdate. This way you can strictly define how and when and what is causing any and all component re-rendering.
Redux is an excellent solution to take care of what you want to do. Personally always use it in my React projects to manage state. Using Redux, you could make your API calls still occur in componentDidMount, however the call can hook into your Redux store and update your initial state. The frees you up from have to worry about the local state of your component and how to go about conditionally rendering everything else in your app. Plus Redux abstracts other functions you need, like re-running your fetchToAPI in certain intervals, into their own source (known as Action Creators). Action Creators hook directly in the Redux store so that when one is used, the resulting state diff is passed to Redux's Reducers, which in turn update the application global state. Then all that needs to be done is to have all of your components that need re-rendering on global state change to listen for state changes that occur in the Redux store and conditionally re-render based on the diff of the store from prevState => newProps. This can be setup fairly easy using the boolean check in componentShouldUpdate.
Hope this helps! Cheers.
Redux passes the data throughout the connected components via prop, given that a component is mounted whenever it receives new props a new render cycle is initiated so it will reflect your changes, moreover if you dont want to use Redux you can try using the new context api which is easy to implement and will also be suitable for your solution here is a tutorial on how to use it
To pass data between pages in next.js you will have to use Redux. The idea of Redux is to have a single source of truth. In redux you update the state by calling actions. To update redux state you have to create something called action creators which dispatches action to update the state.
Answer to your question as to if components on another page can fetch data without the user accessing the page is that they do not need to access the data. The components are mounted only when they are accessed, so it will fetch the data when they are mounted.
Regarding the state change notification, refer to below image, and hopefully it is worth one thousand of words:
Original article here.
I am reading up on react lifecycle and am getting a little confused. Some recommend using componentWillMount to make ajax calls:
https://hashnode.com/post/why-is-it-a-bad-idea-to-call-setstate-immediately-after-componentdidmount-in-react-cim5vz8kn01flek53aqa22mby
Calling setState in componentDidMount will trigger another render()
call and it can lead to layout thrashing.
and in other places it says not to put ajax calls in the componentWillMount:
https://medium.com/#baphemot/understanding-reactjs-component-life-cycle-823a640b3e8d
...this function might end up being called multiple times before the
initial render is called so might result in triggering multiple
side-effects. Due to this fact it is not recommended to use this
function for any side-effect causing operations.
Which is correct?
The React docs recommend on using componentDidMount for making network Requests
componentDidMount() is invoked immediately after a component is
mounted. 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.
Calling setState() in this method will trigger an extra rendering, but
it is guaranteed to flush during the same tick. This guarantees that
even though the render() will be called twice in this case, the user
won’t see the intermediate state.
As per the case for componentWillMount:
EDIT:
This lifecycle is deprecated since v16.3.0 of react and is no longer encouraged for usage.However its renamed to UNSAFE_componentWillUpdate and is expected to work till at least v17 of react
Before v16.3.0
An asynchronous call to fetch data will not return before the render happens. This means the component will render with empty data at least once.
There is no way to “pause” rendering to wait for data to arrive. You cannot return a promise from componentWillMount or wrangle in a setTimeout somehow. The right way to handle this is to setup the component’s initial state so that it’s valid for rendering.
To Sum it up
In practice, componentDidMount is the best place to put calls to fetch data, for two reasons:
Using DidMount makes it clear that data won’t be loaded until after
the initial render. This reminds you to set up initial state
properly, so you don’t end up with undefined state that causes
errors.
If you ever need to render your app on the server, componentWillMount will actually be
called twice – once 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.
componentDidMount is the recommended lifecycle method to make Ajax calls as described in their docs
ComponentDidMount is the place.
But if you have time try to look at Redux and make the requests in actions, as your application grow it will help a lot to manage the app state.
;)