我正在为我的应用使用 Firebase 身份验证。我使用了 here 中的 useAuth 钩子。与关于重定向 (Auth) 的 react-router guide 集成。
SignIn,SignOut
函数按预期工作。但是当我尝试刷新页面时。它再次重定向到 /login
。
我的预期:通过身份验证后重定向到 /
路由。
我尝试在 PrivateRoute.js 中添加此代码
if (auth.loading) {
return <div>authenticating...</div>;
}
所以我可以在不重定向到 /login
的情况下刷新页面,但是当点击 authenticating...
按钮时它只显示 log out
。
这是我的代码:https://codesandbox.io/s/frosty-jennings-j1m1f?file=/src/PrivateRoute.js
我错过了什么?谢谢!
答案 0 :(得分:1)
似乎您没有充分呈现“正在验证”的加载状态。
我认为,当初始身份验证检查解决时,您没有正确清除 loading
中的 useEffect
中的 useAuth
状态。
每当启动身份验证检查或操作时将 loading
设置为真,并在检查或操作完成时清除。
使用身份验证
function useProvideAuth() {
const [loading, setLoading] = useState(true); // <-- initial true for initial mount render
const [user, setUser] = useState(null);
// Wrap any Firebase methods we want to use making sure ...
// ... to save the user to state.
const signin = (email, password) => {
setLoading(true); // <-- loading true when signing in
return firebase
.auth()
.signInWithEmailAndPassword(email, password)
.then((response) => {
setUser(response.user);
return response.user;
})
.finally(() => setLoading(false)); // <-- clear
};
const signout = () => {
setLoading(true); // <-- loading true when signing out
return firebase
.auth()
.signOut()
.then(() => {
setUser(false);
})
.finally(() => setLoading(false)); // <-- clear
};
// Subscribe to user on mount
// Because this sets state in the callback it will cause any ...
// ... component that utilizes this hook to re-render with the ...
// ... latest auth object.
useEffect(() => {
const unsubscribe = firebase.auth().onAuthStateChanged((user) => {
if (user) {
setUser(user);
} else {
setUser(false);
}
setLoading(false); // <-- clear
});
// Cleanup subscription on unmount
return () => unsubscribe();
}, []);
// Return the user object and auth methods
return {
loading,
user,
signin,
signout
};
}
检查 PrivateRoute
中的加载状态
function PrivateRoute({ children, ...rest }) {
const auth = useAuth();
if (auth.loading) return "authenticating";
return (
<Route
{...rest}
render={({ location }) =>
auth.user ? (
children
) : (
<Redirect
to={{
pathname: "/login",
state: { from: location }
}}
/>
)
}
/>
);
}
答案 1 :(得分:0)
试试这个方法,它对我有用:
const mapStateToProps = state => ({
...state
});
function ConnectedApp() {
const [auth, profile] = useAuth()
const [isLoggedIn, setIsLoggedIn] = useState(false)
useEffect(() => {
if (auth && auth.uid) {
setIsLoggedIn(true)
} else {
setIsLoggedIn(false)
}
}, [auth, profile]);
return (<Router>
<Redirect to="/app/home"/>
<div className="App">
<Switch>
<Route path="/home"><Home/></Route>
<Route path="/login"><Login styles={currentStyles}/></Route>
<Route path="/logout"><Logout styles={currentStyles}/></Route>
<Route path="/signup" render={isLoggedIn
? () => <Redirect to="/app/home"/>
: () => <Signup styles={currentStyles}/>}/>
<Route path="/profile" render={isLoggedIn
? () => <Profile styles={currentStyles}/>
: () => <Redirect to="/login"/>}/>
</Switch>
</div>
</Router>);
}
const App = connect(mapStateToProps)(ConnectedApp)
export default App;