Как обновить список элементов бокового меню в приложении ionic react после входа в систему

#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. Да, но как мне это сделать из несвязанного компонента, такого как «Форум»?