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 得到:

Functions are not valid as a React child. This may happen if you return a Component instead of from render

显然新的 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 },

当我在循环中尝试 return Component 时,我得到:

React.jsx: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

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 (a.k.a.JSX) 而不是 javascript ( 即 if-statement).

由于您似乎批量呈现经过身份验证的路由,因此更优化的解决方案是将它们全部包装在一个检查令牌的 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" />;
};

不要忘记从地图回调中 return Route

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