I created an ionic react app with tabs starter template from the cli and added login functionality to the existing structure.
What I did :
App.tsx
const App: React.FC = () => (
<IonApp>
<IonReactRouter>
<IonTabs>
<IonRouterOutlet>
<Route path="/profile" component={Profile} exact={true} />
<Route path="/history" component={History} />
<Route path="/login" component={Login} exact={true} />
<Route path="/" component={Login} exact={true} />
</IonRouterOutlet>
<IonTabBar slot="bottom">
<IonTabButton tab="profile" href="/profile">
<IonIcon icon={personCircleOutline} />
<IonLabel>Profile</IonLabel>
</IonTabButton>
<IonTabButton tab="history" href="/history">
<IonIcon icon={documentTextOutline} />
<IonLabel>History</IonLabel>
</IonTabButton>
</IonTabBar>
</IonTabs>
</IonReactRouter>
</IonApp>
);
The issue is that I'm seeing all the tabs on the login screen. I want the tabs to show only after the user logs in.
Working Demo here
You need to separate your private tabs into another component:
mainTabs.tsx
const MainTabs: React.FC = () => {
return (
<IonTabs>
<IonRouterOutlet>
<Redirect exact path="/" to="/profile" />
<Route path="/profile" render={() => <Profile />} exact={true} />
<Route path="history" render={() => <History />} exact={true} />
</IonRouterOutlet>
<IonTabBar slot="bottom">
<IonTabButton tab="profile" href="/profile">
<IonIcon icon={personCircleOutline} />
<IonLabel>Profile</IonLabel>
</IonTabButton>
<IonTabButton tab="history" href="/history">
<IonIcon icon={documentTextOutline} />
<IonLabel>History</IonLabel>
</IonTabButton>
</IonTabBar>
</IonTabs>
);
};
export default MainTabs;
After that, you can create a route inside App.tsx in which you conditionally render the private Tabs if the user is logged in. Otherwise, the Login page is rendered:
App.tsx
return (
<IonApp>
<IonReactRouter>
<Route path="/login" component={Login} exact={true} />
<Route path="/" component={isLoggedIn ? MainTabs : Login} />
</IonReactRouter>
</IonApp>
);
At this point, you want to have some sort of state management setup (Redux, custom state management through React hooks, etc.) because you need to have your isLoggedIn
state inside the App component but modify it from the Login component (this get's messy real quick using props only).
So as a quick example (you can definitely do a better job), I've created a simple user
context, in which I inject the function that updates the isLoggedIn
state:
App.tsx
interface IUserManager {
setIsLoggedIn: Function;
}
const user: IUserManager = {
setIsLoggedIn: () => {}
};
export const UserContext = React.createContext<IUserManager>(user);
const IonicApp: React.FC = () => {
const [isLoggedIn, setIsLoggedIn] = useState(false);
const user = useContext(UserContext);
user.setIsLoggedIn = setIsLoggedIn;
return (
<IonApp>
<IonReactRouter>
<Route path="/login" component={Login} exact={true} />
<Route path="/" component={isLoggedIn ? MainTabs : Login} />
</IonReactRouter>
</IonApp>
);
};
const App: React.FC = () => {
return (
<UserContext.Provider value={user}>
<IonicApp />
</UserContext.Provider>
);
};
I also need to create a top-level App
component so I can provide the context and use it right away inside the IonApp
component. After that, I can simply use the user
context inside the Login
component and update the state on login:
const user = useContext(UserContext);
const loginClick = () => {
if (userName === "a" && password === "a") {
user.setIsLoggedIn(true);
}
};
Here is your forked demo.