Context / middleware in React router 7


How to set a context in Reactrouter 7

In this post I will show you how I have find to use a context with middleware in Reactrouter 7 project

Setup our middleware features

Before you create a context we add and set the middleware feature in react router 7 to true.

react-router.config.ts
import type { Config } from "@react-router/dev/config";
export default {
  // Config options...
  // Server-side render by default, to enable SPA mode set this to `false`
  future: {
    v8_middleware: true,
  },
  ssr: true
} satisfies Config;
 

After that we have the middleware feature active into our project.

We should got an error if we run the project, if not we first run this command to see the error :

Terminal
npx run typecheck

We have to edit at least one file :

We see that we have those errors, in file : home.tsx (and) app.ts

Error
> typecheck
> react-router typegen && tsc -b
app/routes/home.tsx:12:29 - error TS2339: Property 'VALUE_FROM_EXPRESS' does not exist on type 'Readonly<RouterContextProvider>'.
12   return { message: context.VALUE_FROM_EXPRESS };
                               ~~~~~~~~~~~~~~~~~~
server/app.ts:16:5 - error TS2322: Type '() => { VALUE_FROM_EXPRESS: string; }' is not assignable to type 'GetLoadContextFunction'.
  Type '{ VALUE_FROM_EXPRESS: string; }' is not assignable to type 'MaybePromise<RouterContextProvider>'.
16     getLoadContext() {
       ~~~~~~~~~~~~~~
  node_modules/@react-router/express/dist/index.d.mts:22:5
    22     getLoadContext?: GetLoadContextFunction;
           ~~~~~~~~~~~~~~
    The expected type comes from property 'getLoadContext' which is declared here on type '{ build: ServerBuild | (() => Promise<ServerBuild>); getLoadContext?: GetLoadContextFunction | undefined; mode?: string | undefined; }'
Found 2 errors.

Now we have to edit only the file app.ts :

And set a new context instead of using : AppContextProvider

server/app.ts
import "react-router";
import { createRequestHandler } from "@react-router/express";
import express from "express";
 
declare module "react-router" {
  interface AppLoadContext {
    VALUE_FROM_EXPRESS: string;
  }
}
 
export const app = express();
 
app.use(
  createRequestHandler({
    build: () => import("virtual:react-router/server-build"),
    getLoadContext() {
      return {
        VALUE_FROM_EXPRESS: "Hello from Express",
      };
    },
  }),
);

Here we are going to use RouterContextProvider

This context is required to any middleware written in our project. Here we don’t have any middleware feature, in the future we should wrote our context in that way for our middleware.

server/app.ts
import "react-router";
import { createRequestHandler } from "@react-router/express";
import express from "express";
import { RouterContextProvider } from "react-router";
 
declare module "react-router" {
 interface RouterContextProvider {
    VALUE_FROM_EXPRESS: string
  }
}
 
export const app = express();
 
app.use(
  createRequestHandler({
    build: () => import("virtual:react-router/server-build"),
    getLoadContext() {
      let context = new RouterContextProvider();
      context.VALUE_FROM_EXPRESS;
      return context;
    },
  }),
);

Here we are going to use RouterContextProvider

This context is required to any middleware written in our project. Here we don’t have any middleware feature, in the future we should wrote our context in that way for our middleware.

Now we can see if we got again the same error when we run the command :

Terminal
npx run typecheck

This post solve our default context, into a context used by our middleware

« We have to redefine our way of spending time through digital tools do we use to speak with »

Yassir Hessane

Digital Native