React Router Middleware is finally here! Here's how to migrate!

React Router middleware is finally here and today we go over how to migrate your apps to use the middleware and why you should!
Transcript
00:00 The day we've been waiting for is finally here! React driver middleware is finally stable and ready to be used. So should you? Well, yes! It's really cool, it allows you to do a lot of cool stuff with your applications and you should be using it if it's really easy for you to migrate especially.
00:23 It's not that hard to migrate depending on your app size and today I'm gonna show you how to both migrate our easy app and hard app and we're gonna be migrating my app from non middleware to middleware and I'm gonna show you all the steps you need to take to do it. So if you're wondering about the reasons why you should migrate or not, well the biggest benefit you get is you can run middleware before and after each loader action and stuff like that. You can protect your routes in one place for example if you have a dashboard you can create a dashboard authentication middleware and protect your whole dashboard from a single place instead of every loader like we did before and there are a lot of other benefits that are kind of niche but important like the fact that you don't have to rely on a custom server for middleware and this is really cool because if you want to for example let's say you're using Express and one day you decide okay I'm gonna use Hono, if you're using middleware from Express you would have to change the implementation to match Hono, but if you're using middleware from React router you can move from one server to the other without any hassle so that's also really cool it allows you to not be locked in as much so you can change your servers and stuff like that.
01:40 Let's migrate my app so I can show you how easy it is. Alright so this is Forge 42's base stack and this is usually the template I use for all my videos. I really love the base stack because it's simple, it gives you a lot of infrastructure for free, and you don't really have to set it up all yourself. And a quick disclaimer, I made this stack and this is what we use internally for all our projects so check it out and with that out of the way let's show you how to implement middleware so the first thing you need to be aware of middleware is stable from version 7.9 so if you're using previous versions upgrade to this one and then we can start migrating. So the first thing you need to do to migrate is you go to your react-router-config and here you just say v8-middleware and true and you've migrated to middleware well it's not as simple as that but if you're using the default server that comes with react art or framework mode this is all you have to do to use middleware because you're not using the custom context for anything so that means you're already using middleware so it's as simple as I just showed you and you can go off of this video but for us crazy people who have custom servers it's a little bit more complicated and I'm gonna show you how to do it as well.
03:05 So if I go to my root TSX, you can see if I save this and if I run it, you can see that I get a bunch of errors and you can also see that this now is complaining. So if I stop this and clear the console... So why does this happen? Well, the lang and the client don't come from this context anymore, that's a naked object, but now it is a map that gives you a get and a set. So a get is used to retrieve a value from context and you're never gonna guess what set is for.
03:42 If you guess that it's for setting values you're pretty much spot-on and you're probably a magician. And I'm not gonna use any of these for now I'm just gonna leave this as it is for it to complain and we're gonna come back to it. This will be your biggest hurdle to overcome if you're using context because this is the only breaking change for custom servers because well not the only breaking change but the only breaking change that requires a lot of rewriting for code so let me show you what you need to do so first let's go to the file that defines the getApp context and or rather getLoad context. And if you're using a custom server, you already know what it is. So this used to return a naked object and it will return the properties you want.
04:30 Well, that's not the case anymore. So what you need to do is you're gonna change this to be something else like get app context and what we are gonna do is we're gonna export const get load context it's gonna be the same signature as it was before so C context and I'm using Hono for my dev server so the C is the context that Hono provides and what we're gonna do is we're gonna return nothing for now and this also complains because this returns absolutely nothing so we're gonna change it to this this is again typed with the correct context and now what we are going to do is because this returns the naked object well the difference is that now you have to create a context here and it's an instance of router context provider class And this class gives you back a context when you initialize it. And now what you can do is you can now get the global object, that's the naked object that's returned by the getAppContext here. And we're gonna do global.ctx is getAppContext. And now we need to await this and we pass it the c here and now we have the naked object and now what we're gonna do is we're gonna set it in our context and we're also gonna return this context and this is all you have to do to get this working so basically extract whatever logic is it was inside of here to a separate function create an instance of router context provider, call the function, get it, and then set it in the context and return that context.
06:26 So how do you set it? Well, you create a variable called global app context. Now this can be called whatever you want, it's really up to you. And you call a method from React Router called createContext. And this will create a default context value for you to provide to your context object that handles all the context in the React Cloud App and we're gonna type it as load context.
06:55 So now if I hover over this you can see that the default value is the load context and now that we have this special object this is used as the first parameter for the set function and then you pass in any value that should be there so in our case that's global context from line 29 And what this does is it sets this value inside of this object and it makes it type safe. So now that we have that in place we are going to go to our entry server now. So now that we changed all of this, this won't return the upload context anymore, is going to create a router context provider and give that as the app context to us. So now instead of accessing it directly, we use the get. And now how do we get it?
07:51 Well if I go back to the context file and go to the global app context, if I export this and then import it inside of here you can see that this doesn't complain anymore. Well, this is how you get stuff from the context now. You have this initializer, and then you set a value inside of it, and then you get it somewhere else. And this is how you get stuff and set stuff in the context or rather the global middleware context and then what you can do here is you can say ctx is equal to and we're basically gonna do this line here and now the language is ctx.lang and also I use hono so I have to do something for the body so we also replace this and that's pretty much it we save this we also remove the upload context and you can see the entry server is not complaining anymore and now the only thing for us to do is actually change the root TSX. And now inside of the root TSX we do the same thing as we did in the entry server.
08:59 So we pass in the global context and we get it and that's pretty much it. Now this is typed, the client environment is this, the language is a string and we are basically migrated to middleware and that's pretty much it. So the only hard part about migrating is actually replacing contacts with this and you're running on middleware. So now I've showed you how to do it and now let's add our first middleware to see how that feels like. So we're gonna type this as route.
09:35 Middleware function array we're gonna say that this returns an array and then this is gonna be fully typed and you get two arguments So the first one is the same as you get in your loaders and the second one is the next function so you call this function to go through this middleware into the loader or into the next middleware depending on how many middlewares you have on the page and we can do something like this so console.log request.url we're gonna say const response is equal to await next and we're also gonna make this async and we're gonna say return response and we're also gonna console log response dot url for example and now we have our first middleware implementation so if I run this so if I run pmp and run dev you can see that it's working now and if I bring up the logs you can see the URL here and the middleware is working and if I do something like headers and if I save this you can see that it returns these headers and that's pretty much it we have our middleware up and running and you can do whatever your heart content and if you're interested in some ideas or what you can do, I have videos on my channel about some middlewares that are really cool like self-committing sessions and using async local storage to actually provide global contacts without having to do something like we do here where we do contacts and then contacts get you can just call it in any function so if you're interested in those you can check it out on the channel and yeah that's it for today I'm really excited about this and I'm actually teaching React Touted courses really soon on Epic Web, so if you're interested feel free to subscribe to the newsletter down below, we're gonna send you the emails when I start doing workshops, and yeah!
11:44 See you in the next one and thank you for watching! Bye!
- Play React Server Components with Vite and React-Router
React Server Components with Vite and React-Router
- Play The future of react-router just got a lot brighter
The future of react-router just got a lot brighter
- Play Let's talk about the future of Remix and react-router
Let's talk about the future of Remix and react-router
- Play Understanding the cause of hydration issues in react-router
Understanding the cause of hydration issues in react-router
- Play Server Components (RSC) in react-router are... actually good?
Server Components (RSC) in react-router are... actually good?
- Play Debug React Router Applications with Custom Logs using react-router-devtools
Debug React Router Applications with Custom Logs using react-router-devtools