#reactjs #ionic-framework #react-props #react-state #side-menu
#reactjs #ionic-framework #react-props #реагировать-состояние #боковое меню
Вопрос:
Я создаю мобильное приложение с помощью ionic react и использовал опцию «ionic start —sidemenu». Это мое приложение.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>
И это компонент Menu.tsx
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>
);
Когда приложение открывается, оно проверяет, зарегистрирован ли пользователь, если нет, перенаправляет на логин. После входа в систему пользователь перенаправляется на страницу форума.
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 amp;amp; <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>
В зависимости от роли пользователя я хочу показывать разные пункты бокового меню, но после успешного входа пользователя в систему элементы sidemenu не обновляются. Каким образом я должен изменить свой код, чтобы он заработал? Заранее спасибо!
Ответ №1:
используйте диспетчер состояний… но для аутентификации я обычно использую контекстный API для сохранения состояния аутентификации, которое затем доступно во всем моем приложении.
Полное решение находится здесь Code from state presentation @ Ioniconf, но stack overflow не нравится, когда вы просто вставляете ссылки, поэтому вот часть кода.
У меня также есть боковое меню в демонстрационном приложении
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;
Оберните приложение контекстом, это мой index.tsx
import { AuthProvider } from "./AuthContext";
ReactDOM.render(
<AuthProvider>
<App />
</AuthProvider>,
document.getElementById("root")
);
Теперь, чтобы использовать его, вы импортируете его
import { useAuth } from "../AuthContext";
Затем в вашем доступе к коду это методы и свойства
const {authInfo} = useAuth();
console.log(authInfo.loggedIn)
Комментарии:
1. Спасибо! Это действительно помогло.
Ответ №2:
Это тривиально. Просто обновите состояние «Заблокировано» на странице «Меню» после входа в систему.
Комментарии:
1. Да, но как мне это сделать из несвязанного компонента, такого как «Форум»?