即使用户在私有路由中进行了身份验证,我也会在页面刷新后重定向到主页?
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 />)} />;
};
问题
问题是您的初始 currentUser
和 loading
状态都是假的。
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='/' />;
};
我正在开发一个私有路由组件,该组件应该阻止未通过身份验证的用户并将他们重定向回主页,在我刷新之前它工作正常,当我刷新页面时当前用户 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 />)} />;
};
问题
问题是您的初始 currentUser
和 loading
状态都是假的。
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='/' />;
};