#How to call loader function in layouts?

1 messages · Page 1 of 1 (latest)

mint scaffold
#

I have create a project for blogging app and I was trying to call the loader function to a components of layouts but couldn't run the loader function as the function runs properly in routes path. I am not sure if I am using the loader correctly or not. My use case is:
I have a folder structure as below:

app
  |-> routes
  |    |-> home.tsx
  |-> components/layout
  |    |-> index.tsx
  |    |-> header.tsx
  |-> routes.ts
// and other files related to the project

My component/layout file contains the layout structure of the application like header footer and so on. And in my components/layout/header.tsx file I want to call the loader is this possible?

My routes.ts contains the code as below:

import { type RouteConfig, index, layout } from "@react-router/dev/routes";

export default [
    layout(
        "components/layout/index.tsx", [
            index("routes/home.tsx")
        ]
    )
] satisfies RouteConfig;

If this is not possible let me know how can I achieve the loader call in header.tsx file because I want to call the loader function to get the dynamic menus from the backend, which I should display in the header menu.

paper wagon
#

yeah you are

#

ok i see

#

header is used inside layout

#

i dont think u can use loaders inside layout

#

Using layout, layout routes create new nesting for their children, but they don't add any segments to the URL. It's like the root route but they can be added at any level.

since theyre not really tied to a url

#

i think what i would do is prolly in the very root

#

return what you need dynamically

#

and then i would access the root's data somehow

#

or maybe even pass it into your reactjs context 🤔

#

assume u want it from the loader function, then yeah

you'd likely habe to take that approach

#

by root i mean the very root.tsx

#

but since its not a route

you cant get it from matches from Route

#

so i think i would have some sort of header context or something

#

and consume it that way

#

maybe someone else has a better idea

this is an interesting problem

i love it when i try to help people but struggle forming my own thoughts lol

cc @full dune @slender tulip

mint scaffold
#

Thank you @paper wagon for your response.

Let's see if someone has an better solution to solve this specific problem.

sleek topaz
#

I'm trying to understand... where do you want the loader data, at layout or header? Each can have its own loader AFAIK

mint scaffold
#

I want my loader in the header.tsx of component/layout directory.

sleek topaz
#

you can call a loader inside your layout route, but in that example your header is a normal React component, not a route. So you could call the loader at layout/index and pass props to the Header component it renders

paper wagon
#

Afaik they are mere wrappers and not routes

So loaders won't work for em?

sleek topaz
#

I ran a quick test here and it worked

#
import { Outlet } from "react-router";

export function loader({}) {
  console.log('running the layout loader')
  return { headerProp: 'I am a prop from the layout loader' }
}


export default function ProjectLayout() {
  return (
    <div>
      <h1>I'm the layout!</h1>
      <main>
        <Outlet />
      </main>
    </div>
  );
}
#

I'd find it very strange if layouts didn't run loaders, I've used it a lot in Remix before RR7

#

but I might be outdated about something

#

Working example:

#
//components/layout/index.tsx
import { Outlet } from "react-router";
import type { Route } from "./+types/index";
import { Header } from './header';

export function loader({}) {
  console.log('running the layout loader')
  return { headerProp: 'I am a prop from the layout loader' }
}


export default function ProjectLayout({ loaderData }: Route.ComponentProps) {
  const { headerProp } = loaderData;
  return (
    <div>
      <h1>I'm the layout!</h1>
      <Header myProp={headerProp} />
      <main>
        <Outlet />
      </main>
    </div>
  );
}

//components/layout/header.tsx
export function Header({ myProp }: { myProp: string }) {
  return (
    <header>
      <h1>Header</h1>
      <p>{myProp}</p>
    </header>
  );
}

#
//routes.ts
import { type RouteConfig, index, layout } from "@react-router/dev/routes";

export default [    layout(
  "components/layout/index.tsx", [
      index("routes/home.tsx")
  ]
)] satisfies RouteConfig;
#

There's one thing I'd probably do different: I wouldn't mix the layout/index file with the layout/header file in the same directory, since the index is a (layout) route and header isn't. I prefer to have all route files together to make it easier to find which ones call loaders, actions and etc

paper wagon
paper wagon
#

yeah i would put header somewhere else

#

prolly under /src/components