组件渲染前useState更新

问题描述 投票:0回答:1

我在 React 应用程序中遇到问题,我对登录端点进行 API 调用。 API返回正确,说明认证成功。但是,我面临两个问题:

apiData 和 isAuth 状态未及时更新,导致在这些状态更新之前导航到登录页面。 因此,应用程序导航到登录页面的速度太快,没有等待状态更新。

使用Api钩子

import axios, { AxiosResponse } from "axios";
import { useEffect, useRef, useState } from "react";

const useApi = <T,>(url: string, method: string, payload?: T) => {
  const [apiData, setApiData] = useState<AxiosResponse>();
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState();

  useEffect(() => {
    const getData = async () => {
      try {
        const response = await axios.request({
          params: payload,
          method,
          url,
        });

        setApiData(response.data);
      } catch (e) {
        setError(e.message);
      } finally {
        setLoading(true);
      }
    };

    getData();
  }, []);

  return { apiData, loading, error };
};

export default useApi;

这是表格

import { useState } from "react";
import { useNavigate } from "react-router-dom";

export const SignIn = () => {
  const [userInfo, setUserInfo] = useState({
    user: "",
    password: "",
  });

  const navigate = useNavigate();

  const submitForm = (e) => {
    e.preventDefault();
    navigate("/user/sign-in", { state: userInfo });
  };

  const updateUser = (newVal: string) => {
    setUserInfo((prev) => ({
      ...prev,
      user: newVal,
    }));
  };

  const updatePassword = (newVal: string) => {
    setUserInfo((prev) => ({
      ...prev,
      password: newVal,
    }));
  };

  return (
    <form onSubmit={(e) => submitForm(e)}>
      <label>username</label>
      <input type="text" onChange={(e) => updateUser(e.target.value)} />

      <label htmlFor="">password</label>
      <input type="password" onChange={(e) => updatePassword(e.target.value)} />

      <button type="submit">submit</button>
    </form>
  );
};

privateRoute,我检查用户是否经过身份验证

import { useEffect, useState } from "react";
import useApi from "../../api/useApi";
import { Navigate, useLocation } from "react-router-dom";
import UserDashboard from "./UserDashboard";

export const PrivateRoute = () => {
  const location = useLocation();

  const { apiData, loading, error } = useApi(
    import.meta.env.VITE_SIGN_IN,
    "GET",
    location.state,
  );

  const [isAuth, setAuth] = useState<boolean>(false);

  useEffect(() => {
    if (apiData?.status === 200) {
      console.log(apiData, "api apiData");
      setAuth(true);
    }
  }, [apiData]);

  return (
    <>
      {isAuth ? (
        <UserDashboard />
      ) : (
        <Navigate to="/sign-in" state={{ from: location.pathname }} />
      )}
    </>
  );
};

reactjs authentication react-hooks react-custom-hooks
1个回答
0
投票
const [isAuth, setAuth] = useState<boolean>(false);

useEffect(() => {
  if (apiData?.status === 200) {
    console.log(apiData, "api apiData");
    setAuth(true);
  }
}, [apiData]);

由于

isAuth
是直接从另一个状态值导出的,所以它不应该是一个独立的状态。这使得您需要编写额外的工作来保持它们同步,通过进行不必要的渲染而导致轻微的性能损失,并引入诸如状态短暂不同步之类的错误。

而是在渲染期间计算值。这将使该值不可能不同步,并让您跳过额外的渲染。

const { apiData, loading, error } = useApi(
  import.meta.env.VITE_SIGN_IN,
  "GET",
  location.state,
);
const isAuth = apiData?.status === 200
© www.soinside.com 2019 - 2024. All rights reserved.