I'm trying to set up a context for Firebase authentication in a React-Ionic app with some protected routes which shouldn't be accessible without being authenticated. So far it kinda works, but not completely. I can log in with no problems and navigate the pages with protected routes, but as soon as I refresh the page, it takes me back to the login page as if I weren't authenticated.
I'm pretty sure I'm messing things up somewhere but haven't been able to detect where (it's actually possible that the whole thing is wrongly implemented, as I'm quite new to this and still learning).
This is how my files look so far (without imports and stuff, just the core part):
App.tsx:
const App: React.FC = () => {
const authContext = useContext(AuthContext);
useEffect(() => {
console.log(authContext) **//**
}, [])
return (
<IonApp>
<IonReactRouter>
<IonRouterOutlet>
<Route exact path="/" component={PageLogin} />
<ProtectedRoute path="/secure/home" component={PageHome} isAuthenticated={authContext.authenticated!}/>
<ProtectedRoute path="/secure/lot/:lotId" component={PageLotOverview} isAuthenticated={authContext.authenticated!}/>
<ProtectedRoute path="/secure/shipment/:shipmentId" component={PageShipmentOverview} isAuthenticated={authContext.authenticated!}/>
</IonRouterOutlet>
</IonReactRouter>
</IonApp>
)
}
AuthProvider.tsx:
export const AuthContext = React.createContext<Partial<ContextProps>>({});
export const AuthProvider = ({ children }: any) => {
const [user, setUser] = useState(null as firebase.User | null);
const [loadingAuthState, setLoadingAuthState] = useState(true);
useEffect(() => {
firebase.auth().onAuthStateChanged((user: any) => {
setUser(user);
setLoadingAuthState(false);
});
}, []);
return (
<AuthContext.Provider
value={{
user,
authenticated: user !== null,
setUser,
loadingAuthState
}}>
{children}
</AuthContext.Provider>
);
}
ProtectedRoute.tsx:
interface ProtectedRouteProps extends RouteProps {
component: React.ComponentType<any>;
path: string;
isAuthenticated: boolean
}
export const ProtectedRoute: React.FC<ProtectedRouteProps> = ({ component: Component, path, isAuthenticated }) => {
useEffect(() => {
console.log("from protected ROUTE", isAuthenticated)
}, [])
return (
<Route path={path} render={() => isAuthenticated ? <Component /> : <Redirect to="/" />} />
);
};
index.tsx:
ReactDOM.render(
<AuthProvider>
<App />
</AuthProvider>
, document.getElementById('root'));
Please let me know if I can provide more useful information. Thanks in advance for your help.
1条答案
按热度按时间wgxvkvu91#
Number 1: Every One are still Learning.
Number 2: There is a very simple solution for this which I personally use (works fine). You can use something called 'session storage' facility.
As soon as you get the user data from Firebase do this :
Session Storage is like a local database that can store any number of values you want to save and don't get erased on refresh. However it is just temporary and will get erased when the user closes the browser window.
Now at every protected routes you can do this.
Pro Tip:
Use can use this mechanism to implement 'Remember Me' option for whatever you are developing. In that case you may have to use
LocalStorage
which is similar tosessionStorage
but it won't erase the data even when the user closes the browser window.And again when the user visits your page, it will automatically redirect the user to the main page without logging in (if you create a
useEffect
to check that).Another thing : Both
localStorage
andsessionStorage
are different for different user. The values stored in my browser'slocalStorage
orsessionStorage
will not be visible to you or anyone for that matter except me.That's it