即使用户在私有路由中进行了身份验证,我也会在页面刷新后重定向到主页?

I am getting redirected to main page after page refresh even if the user is authenticated in private route react?

我正在开发一个私有路由组件,该组件应该阻止未通过身份验证的用户并将他们重定向回主页,在我刷新之前它工作正常,当我刷新页面时当前用户 var 变空一秒钟然后它获取值从而触发重定向到 main,问题是即使用户刷新页面 hi 将被刷新到 main 并且他将不得不再次注册..即使他已登录

// Auth context
 const history = useHistory();
  const location = useLocation();
  const [currentUser, setCurrentUser] = useState<null | any>(null);
  const [currentClient, setCurrentClient] = useState<null | any>(null);
  const [loading, setLoading] = useState<boolean>(false);

  const context = useContext(exercisesContext);
  const _miscContext = useContext(miscContext);

  console.log(_miscContext);
  useEffect(() => {
    setLoading(true);
    //  with unsubscribe logic !!
    //const unsubscribe =
    onAuthStateChanged(auth, (user: any) => {
      console.log(user, 'test................................');
      // if (!user?.email_verified) {
      //  _miscContext.SetSnackBarMsg(true, 'Please verify your email');
      //  return;
      // }
      setCurrentUser(user);
      setLoading(false);
    });
    //return unsubscribe();
  }, []);

  const Signin = (email: string, password: string) => {
    signInWithEmailAndPassword(auth, email, password)
      .then((userCredential) => {
        const { user } = userCredential;
        console.log(userCredential.user.emailVerified, 'pppppppp');
        if (!user.emailVerified) {
          _miscContext.SetSnackBarMsg(true, 'Please verify your email');
          return;
        }
        // Signed in
        //const user = userCredential.user;
        //if (user) {
        history.push('/createtraining');
        // }
      })
      .catch((error) => {
        const errorCode = error.code;
        console.log(errorCode);
      });
  };

  const Signup = async (email: string, password: string, userType: string) => {
    await createUserWithEmailAndPassword(auth, email, password)
      .then((userCredential) => {
        //email_verified;

        setDoc(doc(db, 'Data', userCredential.user.uid), {
          createdAt: Timestamp.now(),
        });

        sendEmailVerification(userCredential.user);
        _miscContext.SetSnackBarMsg(true, 'Please check your email');
      })
      .catch((error) => {
        const errorCode = error.code;
        //const errorMessage = error.message;
        console.log(errorCode);
        if (errorCode === 'auth/weak-password') {
          _miscContext.SetSnackBarMsg(true, 'Password must be at least 6 charechters.');
          history.push('/');
        }
        if (errorCode === 'auth/email-already-in-use') {
          _miscContext.SetSnackBarMsg(true, 'Email already exists.');
          history.push('/');
        }
      });
    _miscContext.SetModal(true, '', 'unit');
  };






  return (
    <authContext.Provider
      value={{
        currentUser,
        currentClient,
        loading,
        Signin,
        Signup,
      }}
    >
      {children}
    </authContext.Provider>
  );
};

// Privite route component 
import React, { useContext } from 'react';
import { Redirect, Route } from 'react-router-dom';
import { authContext } from '../context/auth/AuthState';

interface Props {
  component: any;
  exact: any;
  path: any;
}

export const PrivateRoute: React.FC<Props> = ({ component: Componenet, ...rest }) => {
  const _authContext = useContext(authContext);
  const { currentUser, loading } = _authContext;
  console.log(currentUser);

  return <Route {...rest} render={(props) => (!currentUser && !loading ? <Redirect to='/' /> : <Componenet />)} />;
};

问题

问题是您的初始 currentUserloading 状态都是假的。

const [currentUser, setCurrentUser] = useState<null | any>(null);
const [loading, setLoading] = useState<boolean>(false);

这意味着当应用最初是 loading/mounting 时,如果用户试图访问受保护的路由,他们将在 [=34 之前被重定向=] firsbase 身份验证检查有机会完成。

export const PrivateRoute: React.FC<Props> = ({ component: Component, ...rest }) => {
  const _authContext = useContext(authContext);
  const { currentUser, loading } = _authContext;
  console.log(currentUser);

  return (
    <Route
      {...rest}
      render={(props) => (!currentUser && !loading
        ? <Redirect to='/' />
        : <Component />
      )}
    />
  );
};

解决方案

一个可能的解决方案是从初始加载状态 true 或不等于您已验证的未验证状态的不确定 currentUser 值开始,并在提交重定向之前使用显式检查或呈现受保护的组件。

示例:

const [currentUser, setCurrentUser] = useState<null | any>();
const [loading, setLoading] = useState<boolean>(true);

...

export const PrivateRoute: React.FC<Props> = (props) => {
  const _authContext = useContext(authContext);
  const { currentUser, loading } = _authContext;
  console.log(currentUser);

  if (currentUser === undefined || loading) {
    return null; // or loading spinner, etc...
  }

  return currentUser
    ? <Route {...props} />
    : <Redirect to='/' />;
};