【问题标题】:How to make this code compatible for react-router v6如何使此代码与 react-router v6 兼容
【发布时间】:2022-01-22 21:45:42
【问题描述】:

在 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;

在 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;

错误提示:[ProtectedRoute] 不是 Route 组件。 Routes 的所有子组件必须是 Route 或

是不是少了什么!谢谢

【问题讨论】:

    标签: javascript reactjs react-router mern


    【解决方案1】:

    react-router-dom 中不再使用自定义路由组件。 Routes 组件只能有 RouteReact.Fragment 组件作为子组件,Route 组件只能有 Routes 或其他 Route 组件作为父组件。

    相反,包装器组件处理业务逻辑,并为嵌套的Route 组件呈现children 属性或Outlet,或为重定向呈现Navigate

    渲染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>
      )}
    />
    

    渲染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>
    

    使用Outlet 的好处是您可以使用单个身份验证包装器组件并将任意数量的嵌套Route 子级渲染到其中,而使用children 方法您无法渲染嵌套路由,除非您将它们包装在Routes 组件。

    【讨论】:

    • 每次刷新页面时它都会推送到主页。我可以添加哪些更改,以便在刷新页面时它保持在同一页面上??
    • @MayankPandey 通常,您使用加载或“挂起”状态不提交渲染路由组件或重定向,直到应用程序确定任何身份验证状态。重新加载页面/应用时loadingisAuthenticated 的值是多少?
    • 如果用户已登录(isAuthenticated),它会将页面推送到主页并将加载设置为 false。
    • @MayankPandey 什么正在导航到您的主页"/"
    • 已认证
    【解决方案2】:

    如何翻转逻辑并像这样检查 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;
    

    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;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-06
      • 1970-01-01
      • 1970-01-01
      • 2022-01-17
      • 2023-01-17
      • 2014-09-03
      • 2012-01-29
      • 2022-08-04
      相关资源
      最近更新 更多