简体   繁体   English

如何使此代码与 react-router v6 兼容

[英]How to make this code compatible for react-router v6

In ProtectedRoute.js I have coded:在 ProtectedRoute.js 中,我编写了代码:

const ProtectedRoute = ({ component: Component, ...rest }) => {
  const { loading, isAuthenticated, user } = useSelector((state) => state.user);
  return (
    <Fragment>
      {!loading && (
          <Routes>
        <Route
          {...rest}
          render={(props) => {
            if (!isAuthenticated) {
              return <Navigate to="/login" />;
            }
            return <Component {...props} />;
          }}
        />
        </Routes>
      )}
    </Fragment>
  );
};

export default ProtectedRoute;

and in App.js I have written as:在 App.js 中我写成:

function App() {
  const { isAuthenticated, user } = useSelector((state) => state.user);
  useEffect(() => {
    WebFont.load({
      google: { families: ["Roboto", "Droid Sans", "Chilanka"] },
    });
    store.dispatch(loadUser());
  }, []);

  return (
    <Router>
      <Header />
      {isAuthenticated && <UserOptions user={user} />}
      <Routes>
        <Route exact path="/" element={<Home />} />
        <Route exact path="/product/:id" element={<ProductDetails />} />
        <Route exact path="/products" element={<Products />} />
        <Route path="/products/:keyword" element={<Products />} />
        <Route exact path="/search" element={<Search />} />
        <Route exact path="/login" element={<Authenticate />} />
        <ProtectedRoute exact path="/account" element={<Profile />} />
      </Routes>
      <Footer />
    </Router>
  );
}

export default App;

Error says: [ProtectedRoute] is not a Route component.错误说:[ProtectedRoute] 不是 Route 组件。 All component children of Routes must be a Route or <React.Fragment>. Routes 的所有子组件必须是 Route 或 <React.Fragment>。

Is there something missing!是不是少了什么东西! Thank you谢谢

In react-router-dom custom route components are no longer used.react-router-dom中不再使用自定义路由组件。 Routes components can have only Route and React.Fragment components as children, and Route components can have only Routes or other Route components as a parent. Routes组件只能有RouteReact.Fragment组件作为子级,而Route组件只能有Routes或其他Route组件作为父级。

Instead wrapper components handle the business logic and either render the children prop or an Outlet for nested Route components, or the Navigate for redirection.相反,包装器组件处理业务逻辑,并为嵌套的Route组件呈现children道具或Outlet ,或为重定向呈现Navigate

Render children渲染children

const ProtectedRoute = ({ children }) => {
  const { loading, isAuthenticated, user } = useSelector((state) => state.user);

  if (loading) return null;

  return isAuthenticated
    ? children
    : <Navigate to="/login" replace />;
};

... ...

<Route
  path="/account"
  element={(
    <ProtectedRoute>
      <Profile />
    </ProtectedRoute>
  )}
/>

Render Outlet渲染Outlet

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

const ProtectedRoute = () => {
  const { loading, isAuthenticated, user } = useSelector((state) => state.user);

  if (loading) return null;

  return isAuthenticated
    ? <Outlet />
    : <Navigate to="/login" replace />;
};

... ...

<Route path="/account" element={<ProtectedRoute />}>
  <Route path="/account" element={<Profile />} />
</Route>

The benefit of using the Outlet is you can use a single auth wrapper component and render any number of nested Route children into them, whereas with the children method you cannot render nested routes unless you wrap them in a Routes component.使用Outlet的好处是您可以使用单个身份验证包装器组件并将任意数量的嵌套Route子级渲染到其中,而使用children方法您无法渲染嵌套路由,除非您将它们包装在Routes组件中。

How about flipping the logic around and checking everything inside ProtectedRoute like this?像这样翻转逻辑并检查 ProtectedRoute 中的所有内容怎么样?

const ProtectedRoute = () => {
  const { loading, isAuthenticated, user } = useSelector((state) => state.user);
  
  if (loading) { return null; }

  if (!isAuthenticated) {
    return <Navigate to="/login" />;
  }

  return <Profile user={user} andWhateverElse={true} />;
};

export default ProtectedRoute;

And

function App() {
  const { isAuthenticated, user } = useSelector((state) => state.user);
  useEffect(() => {
    WebFont.load({
      google: { families: ["Roboto", "Droid Sans", "Chilanka"] },
    });
    store.dispatch(loadUser());
  }, []);

  return (
    <Router>
      <Header />
      {isAuthenticated && <UserOptions user={user} />}
      <Routes>
        <Route exact path="/" element={<Home />} />
        <Route exact path="/product/:id" element={<ProductDetails />} />
        <Route exact path="/products" element={<Products />} />
        <Route path="/products/:keyword" element={<Products />} />
        <Route exact path="/search" element={<Search />} />
        <Route exact path="/login" element={<Authenticate />} />
        <Route exact path="/account" element={<ProtectedRoute />} />
      </Routes>
      <Footer />
    </Router>
  );
}

export default App;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM