In my Ionic app, I have a login screen and a dashboard screen.
When log in succeeds in Login.tsx, a user is created, then console.log("Go to dashboard")
runs, followed by history.push("/dashboard")
, which should show the Dashboard. The problem is that history.push
changes the url to /dashboard but the dashboard page is not shown and I only still see the login view, even though "Stay in Dashboard"
is printed in the console. If I then refresh the page, the correct Dashboard view is shown.
How do I fix this? Is this because Ionic cannot use isHistory? I also tried using import { useHistory } from "react-router-dom";
in Login screen instead of getting history from props with the same result. What is the correct way to change route in Ionic-React?
App.tsx
...
const App: React.FC = () => (
<IonApp>
<IonReactRouter>
<IonRouterOutlet>
<Route exact path="/login" component={Login} />
<Route exact path="/dashboard"><Dashboard /></Route>
<Route exact path="/"><Redirect to="/login" /></Route>
</IonRouterOutlet>
</IonReactRouter>
</IonApp>
);
Login.tsx
import React, { useEffect, useState } from 'react';
import { RouteComponentProps } from "react-router-dom";
import { useAuthState } from "react-firebase-hooks/auth";
import { auth } from "../config/firebase";
const Login: React.FC<RouteComponentProps> = ({ history }) => {
// const history = useHistory();
const [ email, setEmail ] = useState<string>("");
const [ password, setPassword ] = useState<string>("");
const [ user, loading, error ] = useAuthState(auth);
useEffect(() => {
if (loading) { return; }
if (user) {
console.log("Go to dashboard")
history.push("/dashboard");
}
}, [user, loading]);
const handleCredentials = () => {
// log in
}
return (
<IonPage className="login-page">
<IonContent fullscreen className="ion-padding ion-text-center">
<IonGrid>
<IonRow>
<IonCol>
<IonItem>
<IonLabel position="floating"> Email</IonLabel>
<IonInput
type="email"
value={email}
onIonChange={(e) => setEmail(e.detail.value!)}
placeholder="Email Address"
></IonInput>
</IonItem>
</IonCol>
</IonRow>
<IonRow>
<IonCol>
<IonItem>
<IonLabel position="floating"> Password</IonLabel>
<IonInput
type="password"
value={password}
onIonChange={(e) => setPassword(e.detail.value!)}
placeholder="Password"
></IonInput>
</IonItem>
</IonCol>
</IonRow>
<IonRow>
<IonCol>
<IonButton className="login__btn" expand="block" onClick={handleCredentials}>Login</IonButton>
</IonCol>
</IonRow>
</IonGrid>
</IonContent>
</IonPage>
);
};
export default Login;
Dashboard.tsx
import React, { useEffect, useState } from "react";
import { RouteComponentProps } from "react-router-dom";
import { useAuthState } from "react-firebase-hooks/auth";
import { auth } from "../config/firebase";
const Login: React.FC<RouteComponentProps> = ({ history }) => {
const [user, loading, error] = useAuthState(auth);
useEffect(() => {
if (loading) { return; }
if (!user) {
console.log("Go to log in");
return history.push("/login");
}
console.log("Stay in Dashboard");
}, [user, loading]);
return (
<div className="dashboard">
<div className="dashboard__container">
Logged in
</div>
</div>
);
}
export default Dashboard;
2
Answers
I just found the answer here: https://github.com/ionic-team/ionic-framework/issues/20707
Simply surround your tags with
<IonPage>
and the redirect works. In my case, I added 2 them into Dashboard and nowhistory.push
works as expected.I have had similar issues in Ionic apps with routing before. One way I was able to resolve them is to render the routes additionally into the
Switch
component. I cannot confirm this is the "correct way", but is has worked for me in past projects.Example: