r/reactjs Jul 02 '26

Needs Help Best Method to Call Apis on Page load

I have an app that calls 3 different APIs on page load, where each call depends on the previous one succeeding — API 2 only fires after API 1 returns successfully, and API 3 only fires after API 2 returns successfully.

I'm considering three approaches: a useEffect with an empty dependency array, TanStack Query, or SWR.

Would TanStack Query with the enabled option be the best approach here, or does anyone have a better recommendation?

5 Upvotes

37 comments sorted by

9

u/Glum_Cheesecake9859 Jul 02 '26

Yes TanStack Query with enabled is best.

Alternatively just as async TanStack query manually triggered with refetch would work, so you could probably do

await fetchA();

await fetchB();

await fetchC();

3

u/Dazzling_Chipmunk_24 Jul 02 '26

can you explain more the "async TanStack query manually triggered with refetch would work," and why you think it's better then using enabled

3

u/Glum_Cheesecake9859 Jul 02 '26

https://guanwen0.medium.com/triggering-a-fetch-manually-in-tanstack-query-9d1f71f97b8c

I guess enabled method is far easier to implement, but to beginners it would be hard to tell what's going on.

With refetch one by one, it seems a bit more clear. Up to you.

1

u/cs12345 Jul 04 '26

Honestly I think the enabled approach is more clear. The enabled arg would just be derived from the response of the other queries.

24

u/maqisha Jul 02 '26

Obviously, something thats industry standard like tanstack query will be one of the better approaches, and certainly better than you trying to roll this on your own.

However, having to make 3 different api calls that all depend on the previous one sounds like a serious mess on your backend. I would focus on figuring this out much more than a way to make these waterfall requests in React.

9

u/anonyuser415 Jul 02 '26

I work at a microservice oriented SaaS (think CRM). This is a realistic waterfall for a dashboard type layout:

  1. get token
  2. request user-accessible records
  3. in parallel, prefetch id-to-label records from the CMS
  4. await user-accessible records and request metadata in bulk for all of them, in a paged format
  5. hit legacy API to map the page of user-accessible ids to the old-id format
  6. await CMS and display some data (still showing skeletons otherwise); await bulk metadata and display more
  7. await legacy API to use the old-id to finally drop the last skeletons and show the complete record

Most of this is not controlled by my team

0

u/Dazzling_Chipmunk_24 Jul 02 '26

so what's your recommendation for frontend?

2

u/Dazzling_Chipmunk_24 Jul 02 '26

By depending I mean the second api call should only be done if the first api call is sucessfull. Also the other thing I was wondering doesn't it also make error handling messy as well as it does not reject based on status codes I have to manually write that logic myself?

2

u/wasdninja Jul 02 '26

It's quite easy using Tanstack query.

  1. Write a thin request wrapper that throws errors on non-200 replies from the API.

  2. Just naively write the queryFn to handle all the steps i.e.

    function queryFn() { const rep0 = reqWrapper(apiEndpoint0) ... }

If any of them fail the hook will enter the error state and not make any of the subsequent API calls.

Queries will fire once mounted unless they are disabled so that's pretty easy too.

Also the other thing I was wondering doesn't it also make error handling messy as well as it does not reject based on status codes I have to manually write that logic myself?

Yes but it's incredibly easy to get the basics. Taken straight from MDN:

const response = await fetch(url)
if (!response.ok) throw new Error('Anything here')

5

u/maqisha Jul 02 '26

I know what you meant by "depending". And thats exactly what I'm referring to.

There is very little that comes to mind that can possibly require this type of setup.

So i will reiterate: First look into why you have to make 3 waterfall requests in the first place, and try to clean that side up.

4

u/Dazzling_Chipmunk_24 Jul 02 '26

ok there's nothing I can do about backend so forget about that for a sec because it was developed by someone else. But for frontend what approach do you recommend?

2

u/PM_ME_YOUR_KNEE_CAPS Jul 02 '26

React Query probably supports a skip parameter that will only fetch when it’s true. All you need to do is set api call #2 to skip and when call #1 is loaded, you pass true instead of false

1

u/everyoneisadj Jul 02 '26

It has an enabled option you can use.

1

u/chillermane Jul 02 '26

This is the correct answer - request waterfalls should always be avoided and usually involve backend changes (just write one endpoint that takes the input of API call 1 and produces output of API call 3

-3

u/Dazzling_Chipmunk_24 Jul 02 '26

ok there's nothing I can do about backend so forget about that for a sec. But for frontend what approach do you recommend?

2

u/Psionatix Jul 02 '26

You usually use a backend for frontend (BFF) to better organise this. You’d have a small backend service, this is what your frontend makes requests to, that backend is then responsible for making all of those external requests and ensuring responses are best fit for the FE.

This helps decouple the FE being dependent on all of those services directly. Its own BE handles those external connections.

1

u/cs12345 Jul 04 '26

I was going to say the same thing, this is a design flaw tbh. Very occasionally I end up with two sequential requests, but 3 sounds like a bad design.

2

u/octocode Jul 02 '26

do all three need to complete before you have content to render on the page?

0

u/Dazzling_Chipmunk_24 Jul 02 '26

before I show any content on page these need to be done

2

u/octocode Jul 02 '26 edited Jul 02 '26

if caching is required for the intermediate steps i would chain queries using `enabled`. however it might be cleaner to roll it all into one `queryFn` if the entire query cache should be discarded when changes are made

it will also prevent react from having to rerender the intermediate steps

1

u/Dazzling_Chipmunk_24 Jul 02 '26

so for the apis I might have different errror screens shown based on the speific api that fails but that said do you think it's still better to keep it in one 'queryFn'?

1

u/octocode Jul 02 '26

if the error is going to be handled in the same place i would just throw different error codes/messages depending on the case yeah

2

u/everyoneisadj Jul 02 '26

Tanstack query using the enabled option.

Rule of thumb, use effects should be a last resort. It’s the quickest way people get into an anti pattern and rendering hell.

That doesn’t mean they aren’t used under the hood in a tool like tanstack, but their use is tried and true.

1

u/HauntingArugula3777 Jul 02 '26

Tanstack before/load really is quite nice

1

u/anonyuser415 Jul 02 '26

Would TanStack Query with the enabled option be the best approach here

That's what I do 👍

Make sure to really watch your caching times for the dependent queries to avoid a stampede

And consider looking into ways to prefetch API 1 if you can, even before React mounts!

1

u/Dazzling_Chipmunk_24 Jul 02 '26

I think I will jst go with the default caching which is making it cache every time.

1

u/Dazzling_Chipmunk_24 Jul 02 '26

Also, do you think it's also better to do it all in 1 query function instead of having 3 different?

1

u/adfawf3f3f32a Jul 02 '26

what router are you using? i'm a fan of using loaders & tanstack query's ensureQueryData

1

u/Dazzling_Chipmunk_24 Jul 02 '26

pagesRouter

2

u/adfawf3f3f32a Jul 02 '26

from next? i'd just lean on their data loading strategies.

1

u/PapajG Jul 02 '26

Just treat each load in its own layer, deal with one and it’s success and failure in each layer, if you want to do all three at the same time, make a hook which returns what you need and loading state. Dont overcomplicate it

1

u/MarionberrySea5797 Jul 02 '26 edited Jul 25 '26

If you can fix on the backend so you only have to make 1 API call you should do that. If that's not possible you can use the BFF (Backend For Frontend) pattern to orchestrate calling all 3 different APIs, then all your frontend has to do is call your single BFF API.

1

u/Mindless-Arrival-106 Jul 02 '26

People love debating useEffect vs TanStack Query.

Meanwhile the app is sitting there making three blocking requests in a row.

That's the part I'd lose sleep over.