【问题标题】:Getting error with createBrowserRouter: useNavigate() may be used only in the context of a <Router> componentcreateBrowserRouter 出错:useNavigate() 只能在 <Router> 组件的上下文中使用
【发布时间】:2022-11-15 18:34:28
【问题描述】:

我正在尝试从 BrowserRoute 组件切换到 React Router 6.4.3 中的 createBrowserRouter 但出现错误:

useNavigate() 只能在组件的上下文中使用。

我该如何解决?错误来自 AuthProvider 组件,我想我需要用 RouterProvider 包装它,但不清楚我该怎么做。

Index.tsx 组件

const container = document.getElementById('root')!;
const root = createRoot(container);

root.render(
  <React.StrictMode>
    <Provider store={store}>
      <AuthProvider>
        <ThemeProvider theme={theme}>
          <App />
        </ThemeProvider>
      </AuthProvider>
    </Provider>
  </React.StrictMode>
);

App.tsx 组件

const router = createBrowserRouter([
  {
    element: <ProtectedRoute />,
    children: [
      {
        path: '/',
        element: <DashboardLayout />,
        children: [
          {
            index: true,
            element: <HomePage />,
          },
          {
            path: 'about',
            element: <AboutPage />,
          },
        ],
      },
    ],
  },
  {
    path: '/auth',
    element: <Auth />,
  },
]);

const App = () => {
  const { isLoading } = useAuth0();

  if (isLoading) {
    return <LoaderPage />;
  }

  return (
    <>
      <Box>
        <CssBaseline />
        <RouterProvider router={router} />
      </Box>
    </>
  );
};

错误来自 AuthProvider.tsx

export const AuthProvider = ({ children }: PropsWithChildren<Auth0ProviderWithConfigProps>): JSX.Element | null => {
  const domain = process.env.REACT_APP_AUTH0_DOMAIN;
  const clientId = process.env.REACT_APP_AUTH0_CLIENT_ID;
  const navigate = useNavigate();
  if (!(domain && clientId)) {
    return null;
  }

  const onRedirectCallback = (appState: any) => {
    navigate(appState?.returnTo || window.location.pathname);
  };

  return (
    <Auth0Provider
      domain={domain}
      clientId={clientId}
      redirectUri={window.location.origin}
      onRedirectCallback={onRedirectCallback}
    >
      {children}
    </Auth0Provider>
  );
};

【问题讨论】:

  • Provider 包装器应该在 Router 包装器内....

标签: reactjs typescript react-router react-router-dom


【解决方案1】:

AuthProvider 组件需要在路由上下文中呈现,以便访问它并使用任何 react-router-dom 挂钩。创建一个布局路由来呈现 AuthProvider 包装 Outlet 组件。

例子:

import {
  createBrowserRouter,
  Outlet
} from 'react-router-dom';

const AuthLayout = () => (
  <AuthProvider>
    <Outlet />
  </AuthProvider>
);

const router = createBrowserRouter([
  {
    element: <AuthLayout />,
    children: [
      {
        element: <ProtectedRoute />,
        children: [
          {
            path: '/',
            element: <DashboardLayout />,
            children: [
              {
                index: true,
                element: <HomePage />,
              },
              {
                path: 'about',
                element: <AboutPage />,
              },
            ],
          },
        ],
      },
      {
        path: '/auth',
        element: <Auth />,
      },
    ]
  },
]);

const App = () => {
  const { isLoading } = useAuth0();

  if (isLoading) {
    return <LoaderPage />;
  }

  return (
    <>
      <Box>
        <CssBaseline />
        <RouterProvider router={router} />
      </Box>
    </>
  );
};

...

const container = document.getElementById('root')!;
const root = createRoot(container);

root.render(
  <React.StrictMode>
    <Provider store={store}>
      <ThemeProvider theme={theme}>
        <App />
      </ThemeProvider>
    </Provider>
  </React.StrictMode>
);

【讨论】:

    【解决方案2】:

    useNavigation 只能在路由上下文中访问。

    在这种情况下,auth 组件是路由的父组件。所以 React 无法识别导航钩子。

    所以你需要在路由中移动 auth 组件。像这样的东西

    <Box>
        <CssBaseline />
        <RouterProvider router={router} >
              <AuthProvider />
        </RouterProvider>
      </Box>
    

    【讨论】:

    • 然后我得到一个错误:Type '{ children: Element;路由器:路由器; }' 不可分配给类型 'IntrinsicAttributes & RouterProviderProps'。 “IntrinsicAttributes & RouterProviderProps”类型上不存在属性“children”。
    猜你喜欢
    • 1970-01-01
    • 2021-12-29
    • 1970-01-01
    • 2022-06-30
    • 2021-01-31
    • 1970-01-01
    • 2021-04-02
    • 2022-11-03
    相关资源
    最近更新 更多