6

I'm trying to lazy load route elements with the createBrowserRouter function in React Router v6 but I keep getting this error: `Matched leaf route at location "/admin/reports/enrollees" does not have an element or Component. This means it will render an with a null value by default resulting in an "empty" page. This is my routes file:

export default createBrowserRouter([
    {
        path: '/admin/reports',
        children: [
            {
                path: '',
                element: <Index />,
            },
            {
                path: 'enrollees',
                lazy: () => import('../../components/Reports/Enrollees'),
            },
            {
                path: 'facilities',
                lazy: () => import('../../components/Reports/Facilities'),
            }
        ],
    }
])

I tried doing this at first:

export default createBrowserRouter([
    {
        path: '/admin/reports',
        children: [
            {
                path: '',
                element: <Index />,
            },
            {
                path: 'enrollees',
                element: lazy(() => import('../../components/Reports/Enrollees')),
            },
            {
                path: 'facilities',
                element: lazy(() => import('../../components/Reports/Facilities')),
            }
        ],
    }
])

But I got the error: Functions are not valid as a React child. This may happen if you return a Component instead of <Component /> from render. Or maybe you meant to call this function rather than return it.

1
  • The code doesn't look incorrect, and appears to match the official lazy loading example. What version of react-router-dom do you have installed? Please edit and share your package.json file, and also run npm list react-router-dom in the terminal in the root project directory to log what is actually installed. Commented May 26, 2023 at 15:19

3 Answers 3

17

I was facing the same issue, i resolved it this way

{
  path: "dashboard",
  lazy: async () => {let { Dashboard } = await import("./pages/Dashboard")
    return { Component: Dashboard }},  
}
Sign up to request clarification or add additional context in comments.

1 Comment

If you export a Component the default imports will work. ` // your component export const Component = () => <h1>Dashboard</h1>; Component.displayName = "Dashboard"; // in routes { path: "dashboard", lazy: () => import("./dashboard") } `
7

This strange problem had been bothering me for a few hours, but I finally figured out the problem

First make sure your component's name is Component, then use named export instead of default export

eg. YourComponent.jsx

export function Component(){
  return <div>something</div>
}

the route object

{
  path: 'your-component',
  lazy: () => import('./YourComponent'),
}

If you want to keep your component name and also use default export, you can do

eg. YourComponent.jsx

export default function YourComponent(){
  return <div>something</div>
}

the route object

{
  path: 'your-component',
  async lazy() {
    let YourComponent = await import("./YourComponent");
    return { Component: YourComponent.default };
  },
}

1 Comment

You don't necessarily need to rename your component to Component...which would make managing the code across many components difficult. Instead, you would add (typically to the end of the component's file) export const Component = MyOriginalComponent; and Component.displayName = 'MyOriginalComponent';. This lets you keep your code in a function that has meaning and that matches its filename, while exporting it in a way that makes React Router happy.
5

Here's a reusable utility function that can make lazy loading routes cleaner (and provides autocomplete for component names):

export const lazyRoute = <T = any>(
  importFn: () => Promise<T>,
  componentName: keyof T
) => async () => {
  const module = await importFn();
  return { Component: module[componentName] };
};

// Usage
const router = createBrowserRouter([
  {
    path: "/admin/reports/enrollees",
    lazy: lazyRoute(() => import("./pages/Reports"), 'ReportsPage'),
  }
]);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.