反应中基于条件的路由

Condition based routing in react

我想根据用户登录渲染路由 status.So,我做了一个函数来检查用户是否在后端使用 axios 进行了身份验证,并在 App 组件的 useEffect 中调用该函数并存储响应在使用状态。然后我在 Route 组件的元素中使用条件。如果用户通过身份验证,则将用户重定向到主页。如果没有,重定向到登录页面。但问题是当我尝试从 url 栏输入路由时,即使我已通过身份验证,我也总是被重定向到登录页面。

这些是我的代码(为了看起来更干净,我删除了一些不相关的代码)

function App() {

  const navigate = useNavigate();

  const [isLoggedIn, setIsLoggedIn] = useState("NOT_LOGGED_IN");
  const [user, setUser] = useState({});

  const verifyLogin = async () => {
    const res = await axios({
      url: "http://localhost:5000/isloggedin",
      method: "get",
      withCredentials: true
    })
    if (res.data.isLoggedIn && isLoggedIn === "NOT_LOGGED_IN") {
      setIsLoggedIn("LOGGED_IN");
      setUser(res.data.user)
    } else if (!res.data.isLoggedIn && isLoggedIn === "LOGGED_IN") {
      setIsLoggedIn("NOT_LOGGED_IN");
      setUser({})
    }
  }

  useEffect(() => {
    verifyLogin()
  }, [])

  return (
    <div className="App">
      <Routes>
        <Route path='/' element={isLoggedIn === "LOGGED_IN" ? <Home isLoggedIn={isLoggedIn} user={user} /> : <Navigate to="/login" />} exact />
        <Route path='/register' element={<Register handleRegister={handleRegister} registerError={registerError} />} />
        <Route path='/register/:userId/info' element={isLoggedIn === "LOGGED_IN" ? <RegisterInfo handleRegister={handleRegister} registerError={registerError} /> : <Navigate to={"/register"} />} />
        <Route path='/login' element={<Login isLoggedIn={isLoggedIn} handleLogin={handleLogin} logout={logout} />} />
      </Routes>
    </div >
  );

  }

如果我的文章让您感到困惑,我深表歉意。我的英语不太好。

问题

问题是您的初始 isLoggedIn 状态与您的未验证状态匹配。当应用程序最初加载并且您尝试访问 any 路由时,应用程序使用此 "NOT_LOGGED_IN" 初始 isLoggedIn 状态值并确定用户未登录并重定向因此。

解决方案

常见的解决方案是从既未经过身份验证也未经过身份验证的“不确定”状态开始,并有条件地不呈现任何内容或加载指示器等...除了路由组件或重定向之外的任何内容。

示例:

function App() {
  const navigate = useNavigate();

  const [isLoggedIn, setIsLoggedIn] = useState(); // <-- initially undefined
  const [user, setUser] = useState({});

  useEffect(() => {
    const verifyLogin = async () => {
      const res = await axios({
        url: "http://localhost:5000/isloggedin",
        method: "get",
        withCredentials: true
      });

      if (res.data.isLoggedIn && isLoggedIn === "NOT_LOGGED_IN") {
        setIsLoggedIn("LOGGED_IN");
        setUser(res.data.user);
      } else if (!res.data.isLoggedIn && isLoggedIn === "LOGGED_IN") {
        setIsLoggedIn("NOT_LOGGED_IN");
        setUser({});
      }
    };

    verifyLogin();
  }, []);

  if (isLoggedIn === undefined) { // <-- check if undefined
    return null; // or loading indicator, etc...
  }

  return (
    <div className="App">
      <Routes>
        <Route
          path='/'
          element={isLoggedIn === "LOGGED_IN"
            ? <Home isLoggedIn={isLoggedIn} user={user} />
            : <Navigate to="/login" />
          }
        />
        <Route
          path='/register'
          element={(
            <Register
              handleRegister={handleRegister}
              registerError={registerError}
            />
          )}
        />
        <Route
          path='/register/:userId/info'
          element={isLoggedIn === "LOGGED_IN"
            ? (
              <RegisterInfo
                handleRegister={handleRegister}
                registerError={registerError}
              />
            )
            : <Navigate to={"/register"} />
          }
        />
        <Route
          path='/login'
          element={(
            <Login
              isLoggedIn={isLoggedIn}
              handleLogin={handleLogin}
              logout={logout}
            />
          )}
        />
      </Routes>
    </div >
  );
}

进一步的建议

  • isLoggedIn 状态和身份验证抽象到 React 上下文中。
  • 摘要 .

这会使您的代码变得更加DRY