拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 React-如何检查用户是否仍然通过身份验证

React-如何检查用户是否仍然通过身份验证

白鹭 - 2022-03-16 2168 0 0

我有一个小应用程序正在回应,我需要检查用户在离开页面后是否仍然通过身份验证。但我的解决方案不起作用。
我认为我在 useEffect 部分做的不好。因为我在第一次渲染时没有用户。
这是一个好的解决方案还是可以以更好/不同的方式完成?

感谢您的任何建议。

登录页面 - 处理登录

  const handleLogin = async (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    try {
      if (!username || !password) {
        setError('Pole musí byt vyplněna!');
        return;
      }

      const userData = await axios.post(
        `${process.env.REACT_APP_BACKEND_URL}/account/login`,
        {
          username,
          password,
        }
      );

      if (!userData) {
        throw new Error();
      }

      setUser(userData.data);
      localStorage.setItem('token', userData.data.token);
      navigate(state?.path || '/home');
    } catch (err: any) {
      setError('Nesprávné jméno nebo heslo!');
    }
  };

应用程序.ts

function App() {
  const [user, setUser] = useState<ICurrentUser>({
    name: '',
    role: '',
    username: '',
  });

  useEffect(() => {
    const checkUser = async () => {
      const token = localStorage.getItem('token');
      if (token !== null) {
        const userData = await axios.get(
          `${process.env.REACT_APP_BACKEND_URL}/account/checkToken`,
          {
            headers: {
              Authorization: `Bearer ${token}`,
            },
          }
        );

        setUser({
          name: `${userData.data.firstname} ${userData.data.lastname}`,
          role: userData.data.role,
          username: userData.data.username,
        });
      }
    };

    checkUser().catch((err) => console.log(err));
  }, []);

  return (
    <>
      <UserContext.Provider value={{ user, setUser }}>
        <Routes>
          <Route path="/" element={<Login />}></Route>
          <Route
            path="/home"
            element={
              <ProtectedRoute>
                <HomePage />
              </ProtectedRoute>
            }
          />
          <Route
            path="stazky"
            element={
              <ProtectedRoute>
                <Stazky />
              </ProtectedRoute>
            }
          />
          <Route
            path="zamestnanci"
            element={
              <ProtectedRoute>
                <Zamestnanci />
              </ProtectedRoute>
            }
          />
          <Route
            path="newZam"
            element={
              <ProtectedRoute>
                <NovyZamestnanec action="create" />
              </ProtectedRoute>
            }
          />
          <Route
            path="zam/:id"
            element={
              <ProtectedRoute>
                <NovyZamestnanec action="edit" />
              </ProtectedRoute>
            }
          />
          <Route
            path="new"
            element={
              <ProtectedRoute>
                <NovaStazka />
              </ProtectedRoute>
            }
          />
          <Route
            path="vozidla"
            element={
              <ProtectedRoute>
                <Vozidla />
              </ProtectedRoute>
            }
          />
          <Route
            path="newVehicle"
            element={
              <ProtectedRoute>
                <NoveVozidlo />
              </ProtectedRoute>
            }
          />
          <Route
            path="*"
            element={
              <ProtectedRoute>
                <NotFound />
              </ProtectedRoute>
            }
          />
        </Routes>
      </UserContext.Provider>
    </>
  );
}

ProtectedRoute.ts

const ProtectedRoute: React.FC<IProps> = ({ children }) => {
  const location = useLocation();
  const { user } = useContext(UserContext);
  const isAuth = !!user.username;

  return isAuth ? (
    <Layout>{children}</Layout>
  ) : (
    <Navigate to="/" replace state={{ path: location.pathname }} />
  );
};

export default ProtectedRoute;

uj5u.com热心网友回复:

我终于想通了怎么做。

唯一需要的是将“加载状态”添加到背景关系中。如果其他人正在为此苦苦挣扎,我会发布我的代码以供参考。

受保护的路由

const ProtectedRoute: React.FC<IProps> = ({ children }) => {
  const location = useLocation();
  const { user, loading } = useContext(UserContext);
  const isAuth = !!user.username;

  if (loading) {
    return <h1>Loading..</h1>;
  }

  return isAuth ? (
    <Layout>{children}</Layout>
  ) : (
    <Navigate to="/" replace state={{ path: location.pathname }} />
  );
};

应用程序.js

function App() {
  const [user, setUser] = useState<ICurrentUser>({
    name: '',
    role: '',
    username: '',
  });
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const checkUser = async () => {
      const token = localStorage.getItem('token');
      if (token !== null) {
        const userData = await axios.get(
          `${process.env.REACT_APP_BACKEND_URL}/account/checkToken`,
          {
            headers: {
              Authorization: `Bearer ${token}`,
            },
          }
        );

        localStorage.setItem('token', userData.data.token);
        setUser({
          name: `${userData.data.firstname} ${userData.data.lastname}`,
          role: userData.data.role,
          username: userData.data.username,
        });

        setLoading(false);
      }
    };

    checkUser();
  }, []);

  return (
    <>
      <UserContext.Provider value={{ user, setUser, loading }}>
        <Routes>
          <Route path="/" element={<Login />}></Route>
          <Route
            path="/home"
            element={
              <ProtectedRoute>
                <HomePage />
              </ProtectedRoute>
            }
          />
          <Route
            path="stazky"
            element={
              <ProtectedRoute>
                <Stazky />
              </ProtectedRoute>
            }
          />
                   </Routes>
      </UserContext.Provider>
    </>
  );
}

语境

interface IContent {
  loading: boolean;
  user: ICurrentUser;
  setUser: (user: ICurrentUser) => void;
}

export const UserContext = createContext<IContent>({
  user: {
    name: '',
    role: '',
    username: '',
  },
  setUser: () => {},
  loading: true,
});
标签:

0 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *