I'm creating a mobile app with ionic react and used the "ionic start --sidemenu" option. This is my App.tsx
<IonApp>
<IonReactRouter>
<IonSplitPane contentId="main">
<Menu isLogged={isLoggedIn} userType={userType} logoutFunc={logout} />
<IonRouterOutlet id="main">
<Route path="/user/auth" render={(props) => isLoggedIn ? <Forum {...props} isLoggedIn={isLoggedIn} /> : <AuthHome {...props} />} exact />
<Route path="/user/register" render={(props) => isLoggedIn ? <Forum {...props} isLoggedIn={isLoggedIn} /> : <Register {...props} />} exact />
<Route path="/user/register-as-owner" render={(props) => isLoggedIn ? <Forum {...props} isLoggedIn={isLoggedIn} /> : <RegisterAsOwner {...props} />} exact />
<Route path="/user/login" render={(props) => isLoggedIn ? <Forum {...props} isLoggedIn={isLoggedIn} /> : <Login {...props} />} exact />
<Route path="/user/profile" render={(props) => <Profile {...props} />} exact />
<Route path="/user/inbox" render={(props) => <Inbox />} exact />
<Route path="/user/inbox/:id" render={(props) => <Mail {...props} />} exact />
<Route path="/user/profile/my-notification" component={MyNotification} exact />
<Route path='/user/create-team' render={(props) => <CreateTeam {...props} />} exact />
<Route path='/list-teams' render={props => <TeamListing {...props} />} exact />
<Route path='/team/:id' render={props => <Team {...props} />} exact />
<Route path="/forum" component={Forum} exact />
<Route path="/game" render={(props) => <CreateGameNotification {...props} />} exact />
<Route path="/game/:id" render={(props) => <GameInfo {...props} />} exact />
<Route path="/game/comments/:id" render={(props) => <GameComments {...props} />} exact />
<Redirect from="/" to={isLoggedIn ? "/forum" : "/user/auth"} exact />
<Redirect from="/user/logout" to="/user/auth" exact />
</IonRouterOutlet>
</IonSplitPane>
</IonReactRouter>
</IonApp>
And this is the Menu.tsx component
const getMenuItem = (appPage: AppPage, index: number) => {
return (
<IonMenuToggle key={appPage + "-" + index} autoHide={false}>
<IonItem className={location.pathname === appPage.url ? 'selected' : ''} routerLink={appPage.url} routerDirection="none" lines="none" detail={false}>
<IonIcon slot="start" ios={appPage.iosIcon} md={appPage.mdIcon} />
<IonLabel>{appPage.title}</IonLabel>
</IonItem>
</IonMenuToggle>
);
};
return (
<IonMenu contentId="main" type="overlay">
<IonContent>
<IonList id="inbox-list">
<IonListHeader>Menu</IonListHeader>
{props.isLogged
? props.userType == "user"
? menuItem.UserMenuPage.map((page: AppPage, i) => getMenuItem(page, i))
: props.userType == "owner"
? menuItem.OwnerMenuPage.map((page: AppPage, i) => getMenuItem(page, i))
: props.userType == "admin"
? menuItem.AdminMenuPage.map((page: AppPage, i) => getMenuItem(page, i))
: <></>
: menuItem.UnauthenticatedUserMenuPage.map((page: AppPage, i) => getMenuItem(page, i))}
<IonMenuToggle autoHide={false}>
<IonItem onClick={e => props.logoutFunc(history)} detail={false}>
<IonIcon slot="start" ios={personSharp} md={personSharp} />
<IonLabel>Dil nga profili</IonLabel>
</IonItem>
</IonMenuToggle>
</IonList>
</IonContent>
</IonMenu>
);
When the app opens it checks if the user is already logged, if not it redirect to the login. After the login the user is redirected to the forum page.
const [gameList, setGameList] = useState<Game[]>();
const [unreadMails, setUnreadMails] = useState<number>(0);
useIonViewWillEnter(() => {
fetch(env.game_api)
.then(res => res.json()
.then(data => {
setGameList(data);
}))
.catch(err => {
console.log(err);
});
authservice.getUserIdFromStorage()
.then(id => {
fetch(env.mail_api + "/user/unread/" + id.value)
.then(resp => resp.json())
.then(res => setUnreadMails(res))
.catch(err => console.log(err));
});
});
<IonPage>
<IonHeader>
<IonToolbar>
<IonButtons slot="start">
<IonMenuButton />
</IonButtons>
<IonTitle color="success">Njoftime</IonTitle>
<IonButton onClick={e => props.history.push("/user/inbox")} slot="end" fill="clear">
<IonIcon icon={mailOutline} size="large"></IonIcon>
{unreadMails > 0 && <IonLabel>{unreadMails}</IonLabel>}
</IonButton>
</IonToolbar>
</IonHeader>
<IonContent fullscreen>
{gameList ? gameList.map((game, i) => {
return (
<IonCard key={game.title + "-" + i} >
<IonCardHeader>
<IonCardTitle>
<IonRouterLink href={"/user/profile?user=" + game.posted_by}>
<IonLabel>{game.posted_by_name}</IonLabel>
</IonRouterLink>
</IonCardTitle>
<IonCardSubtitle>Shkodra Fc</IonCardSubtitle>
</IonCardHeader>
<IonItem routerLink={"/game/" + game._id} >
<IonIcon icon={footballOutline} slot="start" />
<IonLabel>Info Mbi ndeshjen</IonLabel>
</IonItem>
<IonItem lines="none" routerLink={"/game/comments/" + game._id}>
<IonIcon icon={chatboxOutline} slot="start" />
<IonLabel>Komente te Tjera</IonLabel>
</IonItem>
</IonCard>
)
}) : <> </>}
</IonContent>
</IonPage>
Depending on the user role I want to show different side menu items but after the user successfully logs in the sidemenu items do not update. In what way do I have to change my code to make it work? Thanks in advance!
use a state manager... but for auth, I usually use the Context API to hold authentication state which is then accessible throughout my app.
The complete solution is here Code from state presentation @ Ioniconf, but stack overflow doesn't like when you just paste links so here is some of the code.
I have a side menu in the demo app also
import React from "react";
// create the context
export type IAuthContext = {
authInfo: {
loggedIn: boolean;
user: {
email: string;
id: string;
};
};
logOut: any;
logIn: any;
};
const AuthContext = React.createContext<any>(undefined);
// create the context provider, we are using use state to ensure that
// we get reactive values from the context...
export const AuthProvider: React.FC = ({ children }) => {
// the reactive values
const [authInfo, setAuthInfo] = React.useState<any>();
const logOut = () => {
return new Promise((resolve) => {
setAuthInfo({ loggedIn: false, user: null });
setTimeout(() => {
return resolve(true);
}, 1000);
});
};
const logIn = (email: string, password: string) => {
return new Promise((resolve) => {
let v = {
loggedIn: true,
user: { email, id: new Date().getTime() + "" },
};
setAuthInfo(v);
setTimeout(() => {
return resolve(true);
}, 1000);
});
};
let v = {
authInfo,
logOut: logOut,
logIn: logIn,
};
return <AuthContext.Provider value={v}>{children}</AuthContext.Provider>;
};
export const useAuth = () => React.useContext(AuthContext) as IAuthContext;
Wrap the app with the context, this is my index.tsx
import { AuthProvider } from "./AuthContext";
ReactDOM.render(
<AuthProvider>
<App />
</AuthProvider>,
document.getElementById("root")
);
Now to use it, you import it
import { useAuth } from "../AuthContext";
Then in your code access, it's methods and properties
const {authInfo} = useAuth();
console.log(authInfo.loggedIn)