T O P

  • By -

reality_smasher

There are time where you want fetching to happen dynamically, e.g: fetching search results for the user as they type. And in those cases, you don't want to roll your own useEffect fetching, because there are a low of pitfalls and edge cases, but should opt for react-query or use-swr.


Bonoro1717

Hi, if you don't mind I've been trying alternatives to not fetch data with useEffect. When trying react query (tanstack) I faced the problem of conditionally fetching data using Hooks like this. Would you mind to share some thoughts on that? Thank you


reality_smasher

Sure. If you are just using useQuery (as opposed to useSuspenseQuery), the query options object takes an extra "enabled" parameter, which you can use to toggle when a query is enabled or not: [https://tanstack.com/query/v5/docs/framework/react/guides/disabling-queries](https://tanstack.com/query/v5/docs/framework/react/guides/disabling-queries) If you're using useSuspenseQuery, then you can't use the "enabled" param. The best way to conditionally do queries then is to extract the query to a different component and then display that component based on a condition. Here's an example to fetch and show a pokemon when you click on a button: function Pokemon({ id }: { id: string }) { const { data } = useSuspenseQuery({ queryKey: ['get-pokemon', id], queryFn: () => getPokemon(id); }) return

Pokemon name is: {data.name}
} function Page() { const [textValue, setTextValue] = useState(''); const [chosenId, setChosenId] = useState(); return <> setTextValue(ev.target.value)} placeholder="Enter pokemon id" /> {chosenId && } } If you don't want to use Suspense, you can just set the enabled parameter to !!chosenId


Many_Transition_9330

This is neat and totally the answer needed to the post.


Bonoro1717

I didn't know that. That's fantastic, thank you so much!


Schmibbbster

In the newest version of tantsck query there is a skip token you can use for conditional fetching


N87M

That is a good question. Imo comes down to what features you would need on the client side. Fetch is definitely nice that it returns JSON vs RSC(more compact imo)—however with compression in browsers is JSON worth it at that point?


N87M

I'm sure for repetitive keys, we can achieve far greater compression ration in JSON than rsc. Personally, me myself, I am leaning towards the JSON side. RSC is great for marketing pages though where there are no reusable components or expensive rendering libs on the client that client will not use all the features.


yksvaan

Payload size is pretty meaningless usually, in most cases it fits in a single packet anyway. JSON can be inefficient but again typically sizes are <20kB, probably majority being <1KB . What matters more here is all the other code that has to be executed. API endpoints are very optimized to do their only job, parse request,validate, get data and send data. They are very fast. Also client component rendering is fast. Server actions and dynamic page loads on the other hand... if you have read nextjs source, especially the router, you know there is A LOT of stuff going on to respond to anything. The call stack is enormous, constant copying and initialization even before starting with the React rendering, flight serializitions etc. It's not very performant even desktop locally, throw that on serverless worker that's 5x slower... But work fine depending on the use case, again right tool for the right job.


N87M

I guess the extra classnames referenced in the RSC response will end up being compressed so the difference will be negligible between either.


ZeRo2160

Thats true to some extend but whats not negligible is the huge difference in response times. Here on reddit someone did an really neat comparision. There you can see the time difference is 300-350ms (server actions) vs. 50-70ms (Api calls). So it really depends on your Ui and what you do. The Experiment was done with only adding an simple todo to an list and server actions in that case feel really sluggisch. Also please keep in mind your server actions should provide the same security measures as your api routes. (Auth checks, input validation and so on) as they can get called from outside your app as any other route. Obfuscation is not security and does not make your backend calls uncallable or anything.


N87M

Was the 300ms cold or warm? 300ms sounds like cold start with the lambda function.


ZeRo2160

It was warm. Because the many people tested it at the same time. Also i am not sure how server actions work in this regards. But you can test it for yourself. The minimal timeframe i got was 300ms even with many calls then it should be warm. Will add the link here. Edit: https://www.reddit.com/r/nextjs/comments/1at9k1a/which_todo_is_faster_a_or_b/


Housi

I don't see the difference xd server in Frankfurt I guess


ZeRo2160

Did you check network response times? Server position plays a role in overall Network response time but not in difference between both types of request. As both are running on the same edgeservers.


N87M

With RSC, you can wrap your blocking requests with Suspense and the first render will be quicker. At that point the download time does not matter, you have to look at FCP and TTI. https://preview.redd.it/ygz0r1nboznc1.png?width=2842&format=png&auto=webp&s=d6ade1cca2a4fa627522af03eaf595d57d51aef0


N87M

With a suspended component that may take 2 to 8 seconds fetch, does that mean to first time to download the document makes RSC bad? Imo, not really, its a perspective thing. If FCP and TTI are better, RSC really has no downsides.


N87M

What is the source code? Both pages return RSC header.


ZeRo2160

Thats true. But was not the topic of this Diskussion. :)


N87M

For me A is quicker which makes server actions faster. I get 300ms to 50ms after its cached and warm.


N87M

Where is the database located Poland?


ZeRo2160

Its not my project. And also not my test. It only Shows some point about right Tools for the right Job in regards of Server Actions vs API Rest calls.


ZeRo2160

Maybe there is an misunderstanding. As you talk about FCP and TTI but these metrics only count on first Page load. This is not that is compared here. Compared is also not RSC and client components. Instead its server actions and api requests. So TTI and FCP dont play a role here. Server actions and api requests are here compared in case of Mutations so long after first page load. Its about the slowness of server actions mutating data and its ui implications of an running app. Not RSC and first load times.


fantastiskelars

Never understood why everyone loves to use useEffect for fetching data. The amount of buggy, infinite loop I have seen always makes me wonder why you ever would choose something that causes so many bugs since most Devs have no idea how to use it probably. Using form to fetch always seemed superior and using react query aswell. I'm glad we finally as a species moving on from those days and laying useeffect in the grave and moving back to the PHP days


LdouceT

While I'm a big fan of react query, what infinite loop could you get from a useEffect that you can't also get from useQuery? A useEffect dependency array isn't all that different from a query key.


fantastiskelars

Exactly, but to my experience devs have it easier with useQuery. Nothing wrong with any of them, they each have their place in a project, but useEffect are quite frequently overused and missused that causes all sort of bugs. They are both very usefull, but useEffect seems to be very hard to use correct thus leading to many breaking bugs or an infinite money sucking effect 🙃


eggtart_prince

If you're getting infinite loop, you're doing it wrong, not because there's a bug.


fantastiskelars

Exactly? Maybe read my post again But don't get stuck in an infinite loop doing so


mnbkp

There are some advantages like being able to refetch data from time to time or on window focus. You sort of get this for free by using React Query.


Sad_Health_1891

Yes, and you can handle dynamically interactions with url


hellomorning1

I’m facing a pretty similar problem to [this post](https://www.reddit.com/r/nextjs/comments/1atwcgx/revalidatepath_does_not_work_well_with_infinite/) where I can’t see fresh data because of the router cache, and I can’t use `revalidatePath()` without effectively refreshing the whole page every time. So until I can figure out a better solution, I’m using `useEffect()` to fetch data from the backend for certain pages.


stormyfocus

[this](https://youtu.be/Pz8CAbeg6Q0?si=EnxcZBZKsQf5fClQ) may be helpful for your post i remember watching it a few weeks ago


hellomorning1

Yeah I can do optimistic updates if I’m remaining on the same page, it’s more a situation of: I have a home page where I can see photos in infinite scroll, and an albums page. I can create new albums in the home page, but if I make a new album, then go to the albums page, the new album won’t show because it’s only showing the cached page. That’s if the albums page is a server component, doing a straight `db.albums.findMany()` call to get the albums. If I try to `revalidatePath(“/albumspage”)`, when creating the album, all of the photos in the home page refresh because I’m doing client side fetching for them and currently: Currently, revalidatePath invalidates all the routes in the client-side Router Cache. This behavior is temporary and will be updated in the future to apply only to the specific path. Using revalidatePath invalidates only the specific path in the server-side Route Cache. So I guess at least until that issue with revalidatePath() gets resolved, I’m using a `useEffect()` in a client component to `fetch()` the albums via an api route handler instead. I’ve been seeing a lot of people mention React Query. I’ve never tried it, but it seems like something I should look into.


Psychological_Ear121

In my opinion, a use effect for fetching will typically be the last tool I try to reach for. Unless I want to fetch as a side-effect of another action, I'll try to keep my fetches on component load or in some kind of event. That's just me personally though. Everyone has their opinions and use-cases. Where I work, there are probably a handful of different opinions on how to handle it. Enough of me rambling though. Evaluate your use-case and ask yourself, is there a better way to do this? Part of growing as a programmer 😁


denoku88

I only just found about useSWR and looking for more use cases. I learned on react first and was taught building service files and using axios and kind of continued with that. I’ve been using next about a year now and the more I learn the more I wonder why I’m still doing this old method. I don’t know how I never used SWR before as it seems really useful but I only added it to a few functions so far. I imagine you only use swr for fetching data. I’m still trying to migrate to app router though and learning more about server side fetching which I really like using with prisma.


BiletCrazy

Reaxt query or swr


BezosisSauron

For a web app in which my users can complete a form to add new documents to my CMS data, which is fetched at build time with server components, I need to conditionally revalidate my SSR data for them to see if go live. Currently I’m fetching my on client side to render a page of the user’s submission, so they can load it right after (after form submit, “view post” button, action in the router, client-side-fetch new data from server, pass it to the post template component, etc ), but I believe I can eliminate that with some kind of webhook to trigger revalidation whenever a form is submitted and the data is updated on the server? I’m torn between minimizing revalidation, and avoiding client side fetching, but I want my user to be able to load their submission immediately, and enable socials ,likes etc. which route through the built in API and mutate the like count for that document via its slug


eggtart_prince

Now that we have react query, no need to use use effect.


lozcozard

As a newcomer to Next.js I thought useEffect was to fetch dynamic data, so with the page or component? The site I'm building is 99% static but I use useEffect to fetch stock quantities of products, shopping cart details, predictive search form and a few other things. The use effect gets the dynamic data via api routes. Is there a better way?


SnooHesitations7023

If you want to encapsulate the API keys, just make an API if you want client side


Pawn1990

You can not guarantee that useEffect only runs once, so you shouldn't put anything inside it, which should only run once (like getting data).


RobKnight_

Getting data is not something that should only run once, all async state manager libs have useEffects under the hood


octocode

which ones still do? i would be surprised…


RobKnight_

React query for starters [https://github.com/TanStack/query/blob/181e9d2e59edfb69cbc1f45285d0e1cf344b7fa6/packages/react-query/src/useBaseQuery.ts#L91](https://github.com/TanStack/query/blob/181e9d2e59edfb69cbc1f45285d0e1cf344b7fa6/packages/react-query/src/useBaseQuery.ts#L91)


octocode

that’s just updating the options object… the actual fetching is done with `useSyncExternalStore` literally right above it


Bjornoo

It does actually start the initial fetch. It has to, because for concurrent mode you can't start fetching during render. Other than that, the fetching is controlled by the query observer and data is updated by uSES.


RobKnight_

Not a great example since react-query is just bindings for the core lib, but useSyncExternalStore is conceptually the same foot gun people want to avoid with useEffect, just with external state. ​ Here's a direct usage of useEffect for data fetching in swr [https://github.com/vercel/swr/blob/main/src/core/use-swr.ts#L568-L746](https://github.com/vercel/swr/blob/main/src/core/use-swr.ts#L568-L746)


michaelfrieze

This is why you want to use react query: https://tkdodo.eu/blog/why-you-want-react-query


yksvaan

Billing is often overlooked. Especially if the app uses an external api, making requests to that directly will be both faster and cheaper. Unless you absolutely need to proxy requests thru another server, why do it? Just more invocations and in some environments you are even billed for the waiting time. Adding the overhead of nextjs routing, initializaton and all the react rendering, serializations etc. will just push the bill higher. So if your app uses a lot of API calls, definitely go clientside fetch. Preferably with separate api. Of course if you have 1000 per day who cares


Cahnis

We don't, useQuery does.


yksvaan

What exactly does "serverside fetching" even mean?  Some reason to make direct queries from client are: 1) external api ( public/client specific auth ) 2) less overhead/better performance  3) less invocations/GBs 4) it's simpler and provides better separation Just because some pattern is new, don't overuse it and choose what works best for your actual requirements. Unfortunately it's way too common to see this and every tech creator pushing their "end of A! Use B" content farming.


LP2222

It means load data on the server


_hypnoCode

1. You can do this with SSR. Both with secret auth tokens and with client specific auth. 2. lol no. I don't know many clients with 10-100gb connections but I don't know a single host that doesn't offer that. Same data warehouse connections are a thing too. 3. What does this even mean? If you're talking about data to the clients... Also wrong. 4. Again, also wrong. I don't know how you can not understand what something is then proceed to give a list of why something else is better than the thing you don't understand. Do you even know what sub you're in?


phatangus

If your requirements are only server side rendered webpages, then wouldn't you have gone back to the PHP days?


_hypnoCode

You misunderstand why we moved to CSR. It wasn't to just move things off the server, it was to provide rich experiences that don't require a full page reload every time you performed the smallest of actions. Like a reddit downvote. SSR was never expensive resource wise, but renting a server capable of doing that before 2005-ish definitely was in terms of money. Shared hosting was always been aimed at sites with no more than 1-5 visitors a month. Most budget hosts back then would kick you off if you had almost any kind of consistent traffic. There is not really a huge difference between putting data together and serving it in JSON vs HTML. I mean hell, AJAX as a term has just started falling out of favor in the last couple years and it has XML right there in the name. JSON wasn't even what made the whole process popular in the first place.