This is super helpful! I'm prepping curriculum on React Router 6 for a Scrimba course I'm making and will be including a section on the data APIs, and this clarified a lot for me. I'd love to see another video that goes into detail on the deferred data sometime.
Great Video! I am wondering if it's possible to call a hook inside the loader function? I might be going down the wrong path, but I am trying to createContext, that has a [auth, setAuth] = useState({}), that stores a JWT, and inside the loader, I want to get that auth state, and get JWT out of it. Maybe you've a better way to handle JWTs in react? Thanks!
Hey Mat - no you can't use hooks in a loader function, I think you'd want to think of it as just javascript and not a react function. So, not hooks, state etc. If you can use a function to fetch a JWT, then you can simply return the result of that function in the loader. You might find something useful in the react router docs about that, not sure.
@@IanLenehan Thank you for your reply! I ended up going down your path, and making a helper class to with a few handy functions. I'm now storing the refresh token in a HttpOnly cookie (that's valid for 2 weeks), and the access token (that's valid for about 5 minutes) in local storage after logging in. This way I can call "getAccessToken" function inside my loader and set the Bearer token from there. Once again, thank you 😄
great video! my question is that i am using firebase as my database and i use a hook to get my data. now to completely change and refactor the hook into a function i have to get rid of the states and the such. my main issue is how to make a cleanup function if the user changes tabs? firebase gives an unsubscribe function but i use this inside a useEffect hook which i cannot use anymore. How do i add a cleanup function to these loader functions
Sorry Mohsin I have been off TH-cam for a while. Good question, I haven't really looked into it much but perhaps you could return the unsubscribe from the loader and call it in a use effect clean up function? Honestly though I'd need to test it out and see how it works
It's a bit unfortunate that the default behavior of the loader prop is to wait with the navigation until the loader resolves, as opposed to navigate immediately and wait (render progress indicator) on the page that is the target of the navigation, which is pretty much how every web application works. Imagine that the request keeps failing because there is some problem with the API. You would never be navigated to the target page with this pattern and you would have to repeatedly click the link to retry. If you were navigated first, and then the data wouldn't load, you wouldn't have the data, but you would at least land on the page where you wanted to go and could retry by hitting the refresh button or the UI could provide a retry button. With the loader mechanism, the only place you can track the progress of the loader is in components which are already rendered (the target component of your route with the loader is only rendered when the loader resolves), so you can still render a progress indicator, but its label should say "you are being redirected..." and if the loader rejects, the error message should say "you could not be redirected to page xyz, because of this and this error", which arguably is a rather odd UX pattern rarely seen in real world. It's a pity that this is the default behavior of the loader mechanism and to achieve the standard UX pattern you have use the utterly complex combination of `Suspense` and `Await` in your component and `defer` in your loader as described in the Deferred Data Guide. A much nicer API would be to have a navigateImmediately flag to the loader prop where one could choose the behavior. The fact that they call the classic immediate navigation Deferred Data Guide only adds to the confusion. What is really deferred with this pattern is the navigation - deferred untill the data (which is always deferred, if it is loaded from somewhere) is loaded.
Oh, and I forgot to mention the case when the user lands directly on the route with the loader. They would see a blank page or a global loader untill the loader resolves.
This is super helpful! I'm prepping curriculum on React Router 6 for a Scrimba course I'm making and will be including a section on the data APIs, and this clarified a lot for me. I'd love to see another video that goes into detail on the deferred data sometime.
Thanks Bob! Glad you found this useful. Yes I'd definitely like to do a video on deferred data. Hopefully soon!
Hey Bob, I learned react thanks to your scrimba React couses.
17:09 I tried to wrap a separate Route with AppWrapper instead of all routes.. and it doesn't work.. Why?
Why do you define a separate async function within the loader functions? Couldn't you await awaitTimeout directly, then return the data?
Great Video! I am wondering if it's possible to call a hook inside the loader function?
I might be going down the wrong path, but I am trying to createContext, that has a [auth, setAuth] = useState({}), that stores a JWT, and inside the loader, I want to get that auth state, and get JWT out of it.
Maybe you've a better way to handle JWTs in react?
Thanks!
Hey Mat - no you can't use hooks in a loader function, I think you'd want to think of it as just javascript and not a react function. So, not hooks, state etc. If you can use a function to fetch a JWT, then you can simply return the result of that function in the loader. You might find something useful in the react router docs about that, not sure.
@@IanLenehan Thank you for your reply! I ended up going down your path, and making a helper class to with a few handy functions. I'm now storing the refresh token in a HttpOnly cookie (that's valid for 2 weeks), and the access token (that's valid for about 5 minutes) in local storage after logging in. This way I can call "getAccessToken" function inside my loader and set the Bearer token from there. Once again, thank you 😄
great video! my question is that i am using firebase as my database and i use a hook to get my data. now to completely change and refactor the hook into a function i have to get rid of the states and the such. my main issue is how to make a cleanup function if the user changes tabs? firebase gives an unsubscribe function but i use this inside a useEffect hook which i cannot use anymore. How do i add a cleanup function to these loader functions
Sorry Mohsin I have been off TH-cam for a while. Good question, I haven't really looked into it much but perhaps you could return the unsubscribe from the loader and call it in a use effect clean up function? Honestly though I'd need to test it out and see how it works
Very helpful, thank you a lot)) One important question - what theme in VSCode you use?)) The one you use looks perfect 🤩
Ah sorry Marina I think I've changed it since then, right now I'm using Lucario which I really like
Awesome video ++++++++++++ 🙂
Thank you! Cheers!
I didn’t know Cristiano Ronaldo’s brother was a programmer
It's a bit unfortunate that the default behavior of the loader prop is to wait with the navigation until the loader resolves, as opposed to navigate immediately and wait (render progress indicator) on the page that is the target of the navigation, which is pretty much how every web application works. Imagine that the request keeps failing because there is some problem with the API. You would never be navigated to the target page with this pattern and you would have to repeatedly click the link to retry. If you were navigated first, and then the data wouldn't load, you wouldn't have the data, but you would at least land on the page where you wanted to go and could retry by hitting the refresh button or the UI could provide a retry button.
With the loader mechanism, the only place you can track the progress of the loader is in components which are already rendered (the target component of your route with the loader is only rendered when the loader resolves), so you can still render a progress indicator, but its label should say "you are being redirected..." and if the loader rejects, the error message should say "you could not be redirected to page xyz, because of this and this error", which arguably is a rather odd UX pattern rarely seen in real world.
It's a pity that this is the default behavior of the loader mechanism and to achieve the standard UX pattern you have use the utterly complex combination of `Suspense` and `Await` in your component and `defer` in your loader as described in the Deferred Data Guide. A much nicer API would be to have a navigateImmediately flag to the loader prop where one could choose the behavior.
The fact that they call the classic immediate navigation Deferred Data Guide only adds to the confusion. What is really deferred with this pattern is the navigation - deferred untill the data (which is always deferred, if it is loaded from somewhere) is loaded.
Oh, and I forgot to mention the case when the user lands directly on the route with the loader. They would see a blank page or a global loader untill the loader resolves.