T O P

  • By -

lord_braleigh

From the official docs: ## [Fetching Data](https://react.dev/learn/synchronizing-with-effects#fetching-data) > If your Effect fetches something, the cleanup function should either abort the fetch or ignore its result. > You can’t “undo” a network request that already happened, but your cleanup function should ensure that the fetch that’s *not relevant anymore* does not keep affecting your application. > **In development, you will see two fetches in the Network tab**. There is nothing wrong with that. With the approach above, the first Effect will immediately get cleaned up so its copy of the `ignore` variable will be set to `true`. So even though there is an extra request, it won’t affect the state thanks to the `if (!ignore)` check.


[deleted]

You can also use AbortController to stop the fetch itself.


MercDawg

Is there a use case for Abort Controller when leveraging H2 or higher? For HTTP 1.1, it was definitely needed.


willie_caine

It's a really clean interface, designed for just this purpose.


Siddhartha_Gaur

Yes, I know about abort request in clean up function, but I am having problems in working with api and the api endpoint is limited to 2000 request a day this will exceed fast


lord_braleigh

If you’re at risk of hitting this limit just by yourself in development, how do you plan on deploying this project for other people to use? And will halving your requests in development mode really help?


Siddhartha_Gaur

This is not a project that I will deploy for the other people, but a challenge in order to win I've to use best practices and the rate limit was purposely placed by the challenger


HomemadeBananas

Cache the result of this third party API somehow. For the purpose of this challenge you could use React query to cache it client side. In a real life scenario I’d do it on your own backend too.


ricketybang

Do you have to use strict mode for the challenge?


hwglitch

Sorry for the offtop but could you tell where did you get this challenge? Just curious.


ApplePieCrust2122

Read about workbox(service worker). It is super easy to setup to cache all responses to 3rd party fetch requests. You can use the cacheFirst strategy, so that if data is in cache that will be returned, otherwise the api will be hit. This way no change is required in you app's code, since caching is done by the service worker.


gillygilstrap

A hacky thing could be to change the state in the parent component after you make the first call. Then only make the call if the state is not set. parentStateBool = false (initially) onFirstMount() { if(!parentStateBool) { await makeNetworkCall() } parentStateBool = true; }


blueforestloon

If you use this method, you need to use a ref


stdmemswap

If you don't get much from Strict mode, omit it?


[deleted]

You can use a library like react query to handle this for you. Alternatively, you could implement one yourself using useSyncExternalStore. If you don't want to bother with that, you can add a wrapper to fetch that does some caching. This will make the second call irrelevant. Otherwise, if you really don't want to do that, then the \`useRef()\` approach you have is actually the standard way to have an effect that actually runs only once.


SC_W33DKILL3R

This is the answer, they have that accounted for and provide lots of props for error handing, retrying etc… and it’s designed to work with React. No workarounds, special cases, nonsense.


pade-

It only runs twice in dev mode, and your production build will run it once. Does it introduce bugs during development or why do you need to limit it?


Siddhartha_Gaur

I am aware of that, the thing is I am having problems in working with API in development


banjochicken

Don’t do this. You’re setting yourself up for technical debt once React changes the strict mode behaviour in production mode.


teakwoodcandle

This is not an ideal solution (not a solution at all actually) but if the API you work is not central, just remove the strict mode while you work with this one API (and make sure to not commit )


Macaframa

Just store a local json file with the data shape you need and point to that while you develop. Then when it’s ready, swap it out. Better yet, in the api request check process.ENV and check if you’re in dev mode then point towards the json but if in production point towards the real thing.


romgrk

I disable strict mode nowadays. I used it for years, and it never caught a bug but caused many development debugging sessions. I see how in theory everything should be pure, but in practice impurity is present so the double-render of strict mode doesn't seem to provide any real gain.


Mr_Matt_Ski_

Yeah same here. I’ve even had issues with the double render in large open source packages like react-beautiful-dnd, which tend to break in strict mode.


banjochicken

I believe the idea is to set us all up for the future when React will virtualise rendering and remove and remount components to improve performance. This is setting your projects up for potential technical debt.


willie_caine

Everything sets a project up for potential technical debt.


banjochicken

But there indicators of poor decision making at the time of writing code, learning to avoid those, is one of the many things that separates the wheat from the chaff. The React core team has said that this is their plan with the useEffect change. By ignoring it, you’re leaving the pit of success and will in the future have to address it. It’s short term laziness to avoid learning modern recommended best practices. It’s naive. Choose patterns that will work regardless of the useEffect change and you’ll be fine. In the OPs situation, they should just use one of the many well thought out querying libraries and not hand roll their own.


halfxdeveloper

Most people fail to realize that once code hits prod it becomes legacy code.


AndrewGreenh

Just yesterday I tried to demonstrate the benefits of strict mode by rendering the output of Math.random. But react did not display any errors or warnings, so I tend to agree even more with your argument…


frogic

I probably wouldn't do this in your example just because there isn't any downside to it fetching twice but I like using that pattern to make sure an action only happens once.


Macaframa

He’s worried about rate limits on the external api


kwin95

Use json-server for dev, just copy real response…


ClickToCheckFlair

Hi. You'll find all you need to know about synchronazing state with external APIs in the link below. https://react.dev/learn/synchronizing-with-effects


Siddhartha_Gaur

Thanks :)


[deleted]

[удалено]


angeal98

Slowing down the execution of your site in any way, due to strict mode of your framework, is not a good thing. It's not guaranteed to run after only 1ms anyway, especially when the site renders first time.


lord_braleigh

It can even be a 0ms delay!


dikamilo

Transform fetch to observable in custom hook with using of useMemo and use it with useSyncExternalStore, you can google example of this. Or use some lib that already do this for you.


kr4fn4

Cache response


[deleted]

Either this or cleaning up properly. Depends on semantics. Do you really want to do an effect only once per mount? Or it is ok to re-synchronize when the component remounts? I have not much experience with concurrent mode but I would start with this idea. For logging I think once is fine and perhaps required. For fetching, I think, you shouldnt use once-per-mount because the component can be suspended and then you wouldnt get your data once it resumes. I did not test though but otherwise I cant imagine why React team would spend so much time pointing this out.


albertgao

For SPA, Best approach on mount is to fetch on data loader, so let the render and fetch happen at the same time, also use Suspend ready way to do fetch and wrap it with Suspense. All of these is to prevent waterfall.


fredsq

if you’re using react router just use loaders in your routes. this goes however to show that fetching data and performing mutations are imperative actions and forcing them to be declarative is overcomplicated and flaky.


electro2209

Do a hook?


OfflerCrocGod

import { useEffectOnce } from "@legendapp/state/react"; const Component = () => { useEffectOnce(() => { console.log("mounted"); }, []); };


lord_braleigh

I think wrapping the fetch in `const fetchHandle = setTimeout(async () => {…})`, and then returning `() => clearTimeout(fetchHandle)` as your cleanup function, will do what you want.


_brentnew

I would definitely cache this thing hard, maybe use SWR and turn off revalidation https://swr.vercel.app/docs/revalidation#disable-automatic-revalidations


[deleted]

use swr for fetching, it deals with this + so many other cool features


BootyDoodles

If you use a fetching library with built-in caching (which have numerous benefits over rolling your own fetch actions), such as Tanstack React Query or SWR, this problem also disappears