Replies: 1 comment
-
This is what the middleware proposal will enable, so I'm going to close this out as a duplicate. |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
My SPA applications use React Router v6.
At present, all loaders operate in parallel to maximize loading speed and enable faster page rendering. This same approach will also apply to the loading of lazy components (introduced in v6.9.0).
However, this approach can pose a challenge when dealing with applications that have a large number of routes and domain areas. In my applications, I frequently encounter situations where I need to perform some async actions prior to entering some router branch. Unfortunately, this isn't currently possible because React Router calls all loaders and loads all lazy components in parallel.
I will provide some code examples to explain why a feature that enables us to pause the loading of loaders and lazy components before performing critical async actions is necessary.
The examples will utilize an async function called
isLoggedIn
to check whether a user is logged in. If the user is not logged in, the function will redirect them to the sign-in page.1. Code duplication
For example, we have the following slice of router three:
Currently, we include the
isLoggedIn
function within each loader, which could make it challenging to maintain as the codebase becomes more complex. Moreover, even if a user is redirected and doesn't view lazy components, they are still loaded.2. Using a higher-order function
A superior solution would be to create a higher-order function that can accept a loader and execute the isLoggedIn function prior to loading it.
For example:
Although this approach represents an improvement, it would still need to be applied to every route, and lazy components would continue to load even if a user has been redirected to a different route.
3. Nested routes become a real problem
Let's take the code from the previous example and add a nested route to the settings route. We can still apply the higher-order function to the parent route for handling the necessary async actions.
As you can see, the higher-order function guard no longer serves its intended purpose, because the loader for the
notification
route will always be called and its lazy component will always be loaded.Essentially, this behavior is similar to that of Promise.all().
This means that we are loading a lot of unnecessary data and calling functions that could potentially lead to unpredictable behavior. While it's possible to prevent this behavior using various tricks and conditions, it can be difficult to maintain and control such code
Proposal
We should still be able to use the usual loaders to perform them in a parallel way.
With that feature, my example would look like this
The addition of this special function allows for many different functions, such as async guards, validation, and any other important async functions that we need to perform before entering different domain areas of our applications. This function would be called before any loaders or lazy components are loaded, and if it returns a redirect, we can prevent the unnecessary loading of lazy components and calling of loaders in that route branch
My Terrible Solution
I have already been using such a behavior model in my projects by utilizing a higher-order function that accepts a RouteObject with an additional property waitFor and returns a regular RouteObject, but with a special loader that performs this behavior. However, it is really terrible to use such unusual loaders. Technically, that loader has a reference to the parent loader Promise and uses it before calling its own loader and loading its lazy components."
I have created a repository with simplified code from my projects and a stackblitz to show how it works quickly.
I hope React Router adds this feature because it's really helpful and important.
Beta Was this translation helpful? Give feedback.
All reactions