Tidak mungkin untuk mengetahui apakah pengguna akan masuk ketika halaman mulai memuat, ada solusi meskipun.
Anda dapat mengingat status autentikasi terakhir ke localStorage untuk mempertahankannya di antara sesi dan antar tab.
Kemudian, saat halaman mulai memuat, Anda dapat secara optimis mengasumsikan bahwa pengguna akan masuk kembali secara otomatis dan menunda dialog sampai Anda dapat yakin (yaitu setelah onAuthStateChanged
diaktifkan). Jika tidak, jika localStorage
kuncinya kosong, Anda dapat langsung menampilkan dialog.
Peristiwa firebase onAuthStateChanged
akan aktif sekitar 2 detik setelah halaman dimuat.
// User signed out in previous session, show dialog immediately because there will be no auto-login
if (!localStorage.getItem('myPage.expectSignIn')) showDialog() // or redirect to sign-in page
firebase.auth().onAuthStateChanged(user => {
if (user) {
// User just signed in, we should not display dialog next time because of firebase auto-login
localStorage.setItem('myPage.expectSignIn', '1')
} else {
// User just signed-out or auto-login failed, we will show sign-in form immediately the next time he loads the page
localStorage.removeItem('myPage.expectSignIn')
// Here implement logic to trigger the login dialog or redirect to sign-in page, if necessary. Don't redirect if dialog is already visible.
// e.g. showDialog()
}
})
Saya menggunakan ini dengan
React dan
react-router . Saya memasukkan kode di atas ke
componentDidMount
dalam komponen root Aplikasi saya. Di sana, dalam render, saya punya beberapa
PrivateRoutes
<Router>
<Switch>
<PrivateRoute
exact path={routes.DASHBOARD}
component={pages.Dashboard}
/>
...
Dan inilah cara PrivateRoute saya diterapkan:
export default function PrivateRoute(props) {
return firebase.auth().currentUser != null
? <Route {...props}/>
: localStorage.getItem('myPage.expectSignIn')
// if user is expected to sign in automatically, display Spinner, otherwise redirect to login page.
? <Spinner centered size={400}/>
: (
<>
Redirecting to sign in page.
{ location.replace(`/login?from=${props.path}`) }
</>
)
}
// Using router Redirect instead of location.replace
// <Redirect
// from={props.path}
// to={{pathname: routes.SIGN_IN, state: {from: props.path}}}
// />