DEV Community

Cover image for Controlling React API Calls With Hooks

Controlling React API Calls With Hooks

Adam Nathaniel Davis on March 05, 2022

I love React. But there are some aspects of the framework that have previously given me fits. One of those aspects is in the careful controlling ...
Collapse
 
ecyrbe profile image
ecyrbe

Hello Adam,

As an alternative setup, one should also consider using react query.
You can control tighly how the stale-while-revalidate caching works and it comes packaged with sensible defaults.

Collapse
 
cliffordfajardo profile image
Clifford Fajardo • Edited

+1 about is react-query here.
React query is a lot simpler than apollo IMO, & is backend agnostic (REST, GQL, etc) & perhaps most importantly for getting started, its just a set of hooks 😄
I really do appreciate the code snippets in this article & thoughts 💭,. Personally, I wouldnt recommend the code in here production usage for a few reasons: There's probably a dozen+ of things that this doesn't handle (caching, request-deduping, cache access, etc), which something like react-query's hooks give you for free & its a very tiny library:

Collapse
 
bytebodger profile image
Adam Nathaniel Davis

I def don't disagree with any of this. I just wanted to point out that it's entirely possible to responsibly manage your API calls without using any third-party package (and without blindly accepting that some of your basic data calls will simply need to be called repeatedly for no functional reason).

Thread Thread
 
cliffordfajardo profile image
Clifford Fajardo

Thanks for the clarification 🙏

Collapse
 
fadhilradh profile image
Fadhil Radhian

Agree to this. React Query is a godsend

Collapse
 
pelv profile image
Alex Benfaremo

I was going to ask him if he ever tried React Query. Great tool

Collapse
 
antonfil profile image
antonfil • Edited

Hi Adam,

Do I understand correctly that the whole App will be rerendered each time I call some api in some inner component instead of only rerendering that inner component? You call 'loadSharedHooks()' which is a hook which uses 'useState' internally in the global App.
The same question about article about 'Global State' which you refence to: dev.to/bytebodger/hacking-react-ho.... Does it also rerender the whole App while Redux rerenders only components with redux-properties have been changed?

Collapse
 
bytebodger profile image
Adam Nathaniel Davis

This depends upon what you mean by "rerender". In fact, I find this subject causes so much confusion - even amongst senior React devs - that I wrote an entire article about it here: dev.to/bytebodger/react-s-render-d...

The synopsis is as follows:

If by "rerender" you mean that the DOM elements generated by the child components will fully re-render (as in, re-paint themselves in the screen), then no, they absolutely will not be 'rerendered". If the props provided to those child components remain unchanged, then there will be no updating of the DOM elements that are generated inside those child elements.

However, if you mean that the logic encapsulated in those child elements will be re-triggered, then yes, that will absolutely happen. A great way to illustrate this is with useEffect(). The logic inside useEffect() will be invoked every time that component is called (with the major caveat that you can stop this behavior by associating the proper set of dependencies in useEffect()). Some people look at this and say, "Aha! You see?? The child component did RERENDER!" But that's not what actually happened.

Every time the child component is invoked, React will spawn the reconciliation process. In other words, React will determine whether it needs to rerender the DOM. And if there is no change to the DOM, no rerendering will occur. But that doesn't mean that the logic in that component doesn't fire.

An even simpler way to illustrate this is to simply drop a console.log("This component was triggered."); into the body of the child component, then observe what happens when the state changes in the higher-level component. You'll see that the console.log() is indeed triggered. But even though it's been "triggered", this is NOT the same as saying that the child component was rerendered.

Collapse
 
antonfil profile image
antonfil

Thanks for the answer. I meant that the logic (including invoking 'render' method) of the entire <App/> component is retriggered and so Virtual DOM of the entire <App/> is regenerated and compared to Real DOM all the time. Don't you think it downgrades performance? With Redux the logic and regenerating of Virtual DOM happens only for affected components.

Thread Thread
 
bytebodger profile image
Adam Nathaniel Davis

Don't you think it downgrades performance?

No. This is taken from the article that I linked to above:

But don't take my word for it. This is directly from the React docs, on the same page that explains the Reconciliation process (emphasis: mine):

It is important to remember that the reconciliation algorithm is an implementation detail. React could rerender the whole app on every action; the end result would be the same. Just to be clear, rerender in this context means calling render for all components, it doesn’t mean React will unmount and remount them. It will only apply the differences following the rules stated in the previous sections.

Thread Thread
 
antonfil profile image
antonfil

If only re-rendering in the Real DOM had mattered to performance then why would React have introduced ‘memo’?

Thread Thread
 
bytebodger profile image
Adam Nathaniel Davis • Edited

Not sure what you're getting at. The React team is telling you, in their own documentation, that this is an "implementation detail". By definition, an "implementation detail" is something that those using the tool shouldn't be trying to concern themselves with. It's a decision that's supposed to be left to the purview of the tool itself. Worrying about implementation details is a micro-optimization. One of the greatest focuses of the React team is the optimization of the reconciliation process. And that team is telling you, in their own official documentation, that this is an implementation detail.

To be clear, I never said "only re-rendering the Real DOM matters to performance". There are many aspects of an application that can hinder performance - for example: slow, unnecessary, or inefficient API calls. But the reconciliation process is an algorithmic one. Worrying about how React works "under the sheets" - when their own team has specifically stated that this is an implementation detail - is like worrying over the performance of a for loop versus Array.prototype.forEach.

Collapse
 
jologe profile image
jologe

You saved me; I had been looking for ages for the reason why react called my API so many times and I couldn't find why. Thank you, trully.

Collapse
 
jzombie profile image
jzombie

This is somewhat unrelated, however, the few times I've used Apollo, it seems that the state would not maintain across development saves. I'm not sure if the issue was with Apollo or with the way things were set up, but it was really annoying.

Collapse
 
bytebodger profile image
Adam Nathaniel Davis

What do you mean by "across development saves"? Are you saying that you load the app, then run it with Apollo API calls, and then you change something in the app, and then run it again, and then the values are not saved?? Because, if that's what you're saying, that's the expected behavior for all asynchronous calls, regardless of the package you're using. You can save the values in some kinda temporary storage (e.g., Local Storage / Session Storage) and then try to intelligently determine whether you need to make the call again. But if you have an app that calls an API, it's going to make that call again every time you reload the app.

Collapse
 
jzombie profile image
jzombie • Edited

TLDR; The entire application would lose state when hot reloading.


If I am running a development version of the app, update a component and hit save, Apollo seems to bust its own local cache, regardless of where the component is in the tree.

Without using Apollo, create-react-app, Next.js, Vue, Svelte, all would show updates to that component in near real-time, regardless if there was an API call which supplied it with data, because typically the app state wouldn't be lost.

It seems w/ Apollo, the entire app would do a hard refresh so all of the components would lose their local state as well.

I'm sure it wasn't set up properly; perhaps it did need a persistence layer after all; just figured that it would have been able to maintain its own state across saves as well without using local / session storage.

Collapse
 
itshi32 profile image
itshi • Edited

What database could you advise for a react application for an on-time connection of 200 - 300 users?
Phone Directory Application
running in docker image as local web portal

Collapse
 
agnel profile image
Agnel Waghela

How about MongoDB?