'Pass State to Private Nested Routes on React Router v6

So, I have set up my React app routing using React Router v6 with nested Routes.

The problem is that when I access any of my Private routes (defined as follows) I lose the state of the session, losing info such as the query params and the referrer (previous path) and I can't seem to figure route how I can pass this state to my Private route component to the children routes.

This is my routing configuration:

App.js:

import routes from './routes';

const App = () => {
    const routing = useRoutes(routes);

    return (
        <ThemeProvider theme={theme}>
            <UserProvider>
                    <GlobalStyles />
                    {routing}
            </UserProvider>
        </ThemeProvider>
    );
};
export default App;

Index.js:

import App from './App';

ReactDOM.render((
  <BrowserRouter>
    <App />
  </BrowserRouter>
), document.getElementById('root'));

Routes.js:

The console.log(location) shows the location.state empty

const Private = ({ component: Component, ...rest }) => {

  const [state] = React.useContext(UserContext);

  const location = useLocation()
  const path = location.pathname

  console.log(location)
  if (state.auth){
    console.log('Authenticated');
    return <Component {...rest} />
  }
    
  else {
    console.log('Not Authenticated')
    return <Navigate to = {'/login?from=' + path} />
  }
  

};


const routes = [
  {
    path: 'app',
    element: <Private component={DashboardLayout} />,
    children: [
      {
        path: 'account', children: [
          { path: 'integrations', element: <Integrations /> },
        ]
      },
      { path: 'dashboard', element: <Dashboard /> },
      { path: 'audiences', element: <Audiences /> },
      { path: 'creatives', element: <Creatives /> },
      { path: 'copywriting', element: <Copywriting /> },


      { path: 'settings', element: <ProjectSettings /> },
      { path: 'user_settings', element: <UserSettings /> },
      
      { path: 'fb_interests', element: <FbInterestsExplorer /> },
      { path: '*', element: <NotFound /> },
    ]
  },
  {
    path: '/',
    element: <MainLayout />,
    children: [
      { path: 'login', element: <Login /> },
      { path: 'user/activate/:user_id', element: <UserConfirmation /> },
      { path: '/', element: <Navigate to="/app/dashboard" /> },
      { path: '*', element: <NotFound /> }
    ]
  }
];

export default routes;

DashboardLayout.js

const DashboardLayout = () => {
  const [isMobileNavOpen, setMobileNavOpen] = useState(false);

  return (
    <DashboardLayoutRoot>
      <DashboardNavbar onMobileNavOpen={() => setMobileNavOpen(true)} />
      <DashboardSidebar
        onMobileClose={() => setMobileNavOpen(false)}
        openMobile={isMobileNavOpen}
      />
      <DashboardLayoutWrapper>
        <DashboardLayoutContainer>
          <DashboardLayoutContent>
            <Outlet />
          </DashboardLayoutContent>
        </DashboardLayoutContainer>
      </DashboardLayoutWrapper>
    </DashboardLayoutRoot>
  );
};

export default DashboardLayout;


Solution 1:[1]

Try this to get the state in v6:

    const location = useLocation()
    console.log(location)
    const state = location.state
    console.log(state)

Solution 2:[2]

This happend with me when spreading an object inside history state.

<MenuItem
  onClick={() => {
    history("/users/form", {
      state: { isNew: false, ...row },
    })
  }}
>
  Edit
</MenuItem>

This fixed the issue

<MenuItem
  onClick={() => {
    history("/users/form", {
      state: {
        isNew: false,
        type: row.type,
        email: row.email,
        kind: row.kind || "",
        role: row.role,
        permissions: row.permissions,
      },
    })
  }}
>
  Edit
</MenuItem>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 ouflak
Solution 2 CESCO