簡體   English   中英

React-Router-Dom 6 - 如何動態渲染組件?

[英]React-Router-Dom 6 - How to dynamically render a component?

我的舊方法:

          <Route
            key={i}
            path={path}
            render={(props) => {
              if (!localStorage.getItem("token")) {
                <Redirect
                to={{ pathname: "/login", state: { from: props.location } }}
                />
              }
              return (
                <AuthLayout>
                  <Component {...props} />
                </AuthLayout>
              );
            }}
          />

用新element替換render給我:

函數作為 React 子項無效。 如果您返回一個組件而不是從渲染中返回,則可能會發生這種情況

顯然,新的 API 只是期望:

          <Route
            key={i}
            path={path}
            element={
                <Component />
            }
          />

我真正想要完成的是動態渲染組件:

        {authProtectedRoutes.map(({ path, Component }, i) => {
          <Route
            key={i}
            path={path}
            element={
              // If no auth token, redirect to login
              if (!token) {
                <Navigate to="/login" />
              } else {
                <AuthLayout>
                  <Component />
                </AuthLayout>
              }
            }
          />
        })}

不知道該怎么做...

編輯:

我的組件數組是這樣的:

const authProtectedRoutes = [
  { path: "/dashboard", Component: Dashboard },
  { path: "/pages-starter", Component: StarterPage },

當我嘗試在循環中返回Component時,我得到:

React.jsx:類型無效——需要一個字符串(對於內置組件)或一個類/函數(對於復合組件)但得到:未定義。 您可能忘記從定義它的文件中導出您的組件,或者您可能混淆了默認導入和命名導入。

element={
  // If no auth token, redirect to login
  if (!token) {
    <Navigate to="/login" />
  } else {
    <AuthLayout>
      <Component />
    </AuthLayout>
  }
}

你不能在 jsx 中間做一個if ,但你可以做一個條件運算符:

element={!token ? (
  <Navigate to="/login" />
) : (
  <AuthLayout>
    <Component />
  </AuthLayout>
)}

element屬性需要一個ReactNode又名 JSX )而不是 javascript(即 if 語句)。

由於您似乎批量呈現經過身份驗證的路由,因此更好的解決方案是將它們全部包裝在一個檢查令牌的AuthLayout組件中。 它沒有渲染children道具,而是渲染了一個用於渲染嵌套路由的Outlet

例子:

const AuthLayout = ({ token }) => {
  // ... existing AuthLayout logic

  return token
    ? (
      <div /* awesome auth layout CSS style */>
        ...
        <Outlet /> // <-- nested routes render here
      </div>
    )
    : <Navigate to="/login" />;
};

不要忘記從 map 回調返回Route

<Route element={<AuthLayout token={token} />}>
  {authProtectedRoutes.map(({ path, Component }) => (
    <Route key={path} path={path} element={<Component />} />
  ))}
</Route>

很好的路由相關問題。 首先,我從 react-router-dom 的 github 找到了有用的代碼示例: https://github.com/remix-run/react-router/blob/2cd8266765925f8e4651d7caf42ebe60ec8e163a/examples/auth/src/App.tsx#L104#L104

在這里,作者建議實現額外的 RequireAuth 組件並在路由設置中使用它,而不是將一些邏輯放在“元素”或“渲染”中,如下所示:

<Route
  path="/protected"
  element={
    <RequireAuth>
      <SomePageComponent />
    </RequireAuth>
  }
....

這種方法將允許將與身份驗證相關的檢查封裝在這個新的 RequireAuth 組件中,從而使您的應用程序路由設置更加“輕量級”

作為一個“簡短”示例,我創建了以下您可以參考的代碼:

function App() {
    return (
        <BrowserRouter>
            <AppRoutes />
        </BrowserRouter>
    );
}


const RequireAuth = ({ children }) => {
    const token = localStorage.getItem('token');
    const currentUrl = useHref();
    return !token ? (
        <Navigate to={`/login?redirect=${currentUrl}`} />
    ) : (
        children
    );
};

const authProtectedRoutes = [
    { path: '/', component: PaymentsPage },
    { path: '/user', component: UserInfoPage },
];

const AppRoutes = () => (
    <Routes>
        {authProtectedRoutes.map((r) => (
            <Route
                key={r.path}
                path={r.path}
                element={
                    <RequireAuth>
                        <AuthLayout>
                            <r.component />
                        </AuthLayout>
                    </RequireAuth>
                }
            />
        ))}
        <Route path="/login" element={<LoginPage />} />
        <Route path="*" element={<NotFoundPage />} />
    </Routes>
);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM