首页 > 解决方案 > 更改路线时状态正在重置

问题描述

我的反应应用程序中有一个Navbar组件。我管理组件内的管理状态Navbar。当我已经在Lag路线上并尝试路由到Medlemar导航栏的管理部分时,它就会消失。这是因为更改路由时管理员状态正在重置。我怎样才能防止这种情况?

导航栏组件:

function Navbar({ data }) {
  const [user, setUser] = useState(null)
  const [admin, setAdmin] = useState(false)
  const [passedData, setData] = useState(undefined)

  useEffect(() => {
    firebase.auth().onAuthStateChanged((user) => {
      setUser(user)
    })

    if (passedData) {
      console.log(passedData)
    } else {
      setData(data)
    }

    if (user) {
      if(passedData !== undefined) {
        firebase.firestore().collection('teams').doc(passedData.teamID).collection('members').doc(user.uid).get().then((snapshot) => {
          const administrator = snapshot.get('role')

          if (administrator === 'admin') {
            setAdmin(true)
          } else {
            setAdmin(false)
          }
        })
      }
    }
  }, [user])

    return (
        <nav className='navbar'>
          <ul className='nav-menu-items'>
            <li className="nav-text">
              <Link to="/">
                <AiIcons.AiFillDashboard size="1.4em" className="icon" />
                <span>Dashboard</span>
              </Link>
            </li>
            <li className="nav-text">
              <Link to="/lag">
                <AiIcons.AiOutlineTeam size="1.4em" className="icon" />
                <span>Lag</span>
              </Link>
            </li>
            <li className="nav-text">
              <Link to="/profil">
                <BsIcons.BsPerson size="1.4em" className="icon" />
                <span>Profil</span>
              </Link>
            </li>
            <li className="nav-text">
              <Link to="/betaling">
                <GiIcons.GiPayMoney size="1.4em" className="icon" />
                <span>Betaling</span>
              </Link>
            </li>
            </ul>
            {admin ? 
              <>
              <span className="admin-text">Admin</span>
              <div className="navbar-divider"></div>
                <ul className="nav-menu-items">
                  <li className="nav-text">
                    <Link to={{
                      pathname: `/lag/${data.teamID}/admin/medlemar`,
                      state: {
                        passedData: data,
                      }
                    }}>
                      <BsIcons.BsPeopleFill className="icon" size="1.4em" />
                      <span>Medlemar</span>
                    </Link>
                  </li>
                </ul>
                </>
            :
              null
            }
        </nav>
    )
}

应用程序.js

function App() {
  return (
    <>
      <Router>
        <Switch>
          <Route path="/" exact component={Home} />
          <Route path="/logg-inn" component={Login} />
          <Route path="/lag/:id" exact component={Team} />
          <Route path="/profil" component={Profile} />
          <Route path="/registrer-deg" component={Signup} />
          <Route path="/lag" exact component={Teams} />
          <Route path="/lag/:id/innstillingar" exact component={TeamSettings} />
          <Route path="/lag/:id/betaling" exact component={Payment} />
          <Route path="/lag/:id/arrangement" exact component={Events} />
          <Route path="/lag/:id/admin/medlemar" component={Members} />
        </Switch>
      </Router>
    </>
  );
}

标签: javascriptreactjsstatereact-router-dom

解决方案


如果您想使用导航栏在路由之间保持状态,那么您应该将其用作包装器组件并用它包装 /lag 路由。

一般来说,最好使用 React Context 或任何其他状态管理库来避免将来出现问题,但我提供的解决方案应该可以工作。

您的 Navbar 组件可以带子项(用于包装目的),并且看起来像这样:

function Navbar({ data, children }) {
    const [user, setUser] = useState(null);
    const [admin, setAdmin] = useState(false);
    const [passedData, setData] = useState(undefined);

    useEffect(() => {
        firebase.auth().onAuthStateChanged((user) => {
            setUser(user);
        });

        if (passedData) {
            console.log(passedData);
        } else {
            setData(data);
        }

        if (user) {
            if (passedData !== undefined) {
                firebase
                    .firestore()
                    .collection('teams')
                    .doc(passedData.teamID)
                    .collection('members')
                    .doc(user.uid)
                    .get()
                    .then((snapshot) => {
                        const administrator = snapshot.get('role');

                        if (administrator === 'admin') {
                            setAdmin(true);
                        } else {
                            setAdmin(false);
                        }
                    });
            }
        }
    }, [user]);

    return (
        <nav className="navbar">
            <ul className="nav-menu-items">
                <li className="nav-text">
                    <Link to="/">
                        <AiIcons.AiFillDashboard
                            size="1.4em"
                            className="icon"
                        />
                        <span>Dashboard</span>
                    </Link>
                </li>
                <li className="nav-text">
                    <Link to="/lag">
                        <AiIcons.AiOutlineTeam size="1.4em" className="icon" />
                        <span>Lag</span>
                    </Link>
                </li>
                <li className="nav-text">
                    <Link to="/profil">
                        <BsIcons.BsPerson size="1.4em" className="icon" />
                        <span>Profil</span>
                    </Link>
                </li>
                <li className="nav-text">
                    <Link to="/betaling">
                        <GiIcons.GiPayMoney size="1.4em" className="icon" />
                        <span>Betaling</span>
                    </Link>
                </li>
            </ul>
            {admin ? (
                <>
                    <span className="admin-text">Admin</span>
                    <div className="navbar-divider"></div>
                    <ul className="nav-menu-items">
                        <li className="nav-text">
                            <Link
                                to={{
                                    pathname: `/lag/${data.teamID}/admin/medlemar`,
                                    state: {
                                        passedData: data,
                                    },
                                }}
                            >
                                <BsIcons.BsPeopleFill
                                    className="icon"
                                    size="1.4em"
                                />
                                <span>Medlemar</span>
                            </Link>
                        </li>
                    </ul>
                </>
            ) : null}

            {children}
        </nav>
    );
}

然后您的应用程序将看起来像这样:

function App() {
    return (
      <>
        <Router>
          <Switch>
            <Route path="/" exact component={Home} />
            <Route path="/logg-inn" component={Login} />
            <Route path="/lag/:id" exact component={Team} />
            <Route path="/profil" component={Profile} />
            <Route path="/registrer-deg" component={Signup} />
            <Navbar>
            <Route path="/lag" exact component={Teams} />
            <Route path="/lag/:id/innstillingar" exact component={TeamSettings} />
            <Route path="/lag/:id/betaling" exact component={Payment} />
            <Route path="/lag/:id/arrangement" exact component={Events} />
            <Route path="/lag/:id/admin/medlemar" component={Members} />
            </Navbar>
          </Switch>
        </Router>
      </>
    );
  }

推荐阅读