Experience @tanstack/router and found that it is not simple - it helped me 'dispel the charm' of Next.js.
Before this, I thought Next.js was very mature and unbeatable in terms of fullstack design. But after reading the documentation of @tanstack/router, I realized that the world is still very open.
The documentation provides comprehensive stackblitz examples. But it wasn't until I actually worked on the project code and pages and wanted to find the best practice examples that I realized how good the examples it provides are.
The last time I felt that examples were good was when I saw examples in the webpack official repository, Next.js had examples, plasmo had examples, and there were many with-xxx examples.
This time, I feel that the examples are good because I have always wanted to find some real-world projects for specific practices. One example should cover all common scenarios, as mentioned in the usual sayings.
Difficulties encountered when writing code#
I started practicing and felt that the difficulty lies in the combination of two technologies. It seems very flexible, and I couldn't choose the best way. I combined them in the most basic way (in one file, I pasted the corresponding glue code). Next, I wanted to optimize endlessly, such as extracting commonly used code into a common file for singleton reuse. There are also multiple layers of parameter passing positions that need to be well divided. This became a task that I couldn't think of in advance or got stuck in after encountering it. I am most looking forward to finding the best practice.
Now, even before finishing reading, I can feel that the best practice is here.
Let's take a look at the Kitchen Sink Example together#
Functional experience#
-
A control panel that demonstrates parameters, which deeply resonates with me. It directly affects the scaffolding and the behavior of page switching.
-
Scene list:
- Basics: login/not logged in, layout, lazy, nested router
- Hidden basics: store logic corresponding to URL parameters; param serialization; param -> deps -> loader processing
- Interaction: handling loader pending state of the router; handling Created state
- Deep interaction: link preloading
Code details - Combination of technical points#
Read it once, similar to retelling the content of the official documentation, but the content is created and expressed by myself. No omissions, no direct copying, just to gain something.
- auth
Loading order - add redirect logic in beforeLoad;
Add context for dependency injection to avoid frequent imports in child routers, so the context also needs to be restrained to avoid adding huge chunks;
From the design of the API, the event cycle is divided into layers according to the scenarios to be considered. In theory, it can be freely expanded indefinitely, but only extremely restrained and successful frameworks can become popular.
Remaining questions: How to handle the loading of the login button? The same goes for logout. After successful login, call invalidate and check if the user is already logged in in the loader to redirect to the default page after login.
- layout
- Based on the file name or folder prefix _layout, or _layout.route.tsx
- Here, the regular `` == `./index` is divided into [ `` == `/route` | `../[folder with the same name as the file]` , `/` == `/index` ]
- data-loader with @tanstack/query
My simple idea - add useQuery in the component code, which is no different from regular use.
Breaking the idea - the built-in loader does not match this, and it cannot pass the query status to the current router. In addition, the context is a unified injection position and does not provide independent space for each layer of the router.
The approach in the kitchen-sink example: place the queryClient in the context and use queryClient's ensureQueryData in the loader. In the component, use useQuery to set the same options and obtain the same data. - State handling of data-loader
Provides the<MatchRoute />
component, which is a bit different from my intuition. Its parameter is the filter parameter, which made me think it was the settle parameter. My habit is usually to use useXXX to judge. But here, a component is provided to respond to changes through functional children. - dataMutation within @tanstack/query
It is consistent with the useMutation of @tanstack/query and does not introduce any new usage when combined.
I have finished reading it once. Part of the charm has been dispelled. Now, I will practice and see if there is anything unclear. If there is, I will continue to record.