tl;dr; Use data() in your loader function and make your headers function pass it on to get headers be dependent on what's happening in the loader function.

I recently rewrote the front end of this website from Remix to react-router v7. A route is a page, which can be something like /about or have a parameter in it like /blog/:slug.

The way react-router v7 (the "framework mode") works is that your route looks like this:


import type { Route } from "./+types/post"

export async function loader({ params }: Route.LoaderArgs) {
  const post = await fetchPost(params.slug)
  return { post }
}

export default function Component({loaderData}: Route.ComponentProps) {
  return <h1>{loaderData.post.title}</h1>
}

So good for so far. But suppose you want this page to have a certain header, depending on the value of the post object. To set headers, you have to add an exported function called, surprise surprise; headers. For example:


export function headers() {
  return {
    "X-Stretchy-Pants": "it's for fun",
  };
}

The headers function is called with a Route.HeaderArgs argument which is an object with the keys called loaderHeaders, parentHeaders, actionHeaders, and errorHeaders.

That loaderHeaders refers back to the loader function and what it returns. You don't get the { post } thing that you returned in the loader. To get custom headers you have to make this change:


+import { data } from "react-router"
import type { Route } from "./+types/post"

+export async function loader({ params }: Route.LoaderArgs) {
+  const post = await fetchPost(params.slug)
+  return data(
+    { post }, 
+    { headers: {joke: post.jokeOfTheDay }}
+  )
+}

+export function headers({ loaderHeaders }: Route.HeadersArgs) {
+  return {
+    "X-Daily-Joke": loaderHeaders.joke
+  };
+}

export default function Component({loaderData}: Route.ComponentProps) {
  return <h1>{loaderData.post.title}</h1>
}

In Remix, which came before react-router v7, you did not have to do this. It was enough to do:


import { json } from "@remix-run/node"

export async function loader({ params }: LoaderFunctionArgs) {

  // ...

  return json(
    { post },
    { 
      headers: {
        "X-Daily-Joke": post.jokeOfTheDay
      }
    },
  )
}

Comments

Your email will never ever be published.

Related posts