React 如何使有条件呈现的导航持续存在

React how to make conditionally rendered navigation persist

我正在学习 React 并正在创建一个 React 桌面应用程序,其中侧边导航必须根据用户的当前位置(由应用程序主体中的标准导航按钮确定)而改变。

可在此处访问该应用程序:https://codesandbox.io/s/conditional-navigation-di8t5?file=/pages/Start.jsx

当用户在应用程序中移动时,我能够使导航选项有条件地呈现。参见示例:从 'Start' 到 'Page A',再到 'Page B'。问题是当他们回到以前的位置时,导航也会恢复。我希望它是这样的,一旦用户到达页面 B 并返回页面 A,页面 B 仍然可以在侧边导航中访问。

根据研究,使用 React Context API 似乎是最好的解决方案。是这种情况,还是我缺少更简单的方法?谢谢。

您可以采用c0m1t提到的方法,使用useLocation来追踪当前位置。

为了能够始终如一地跟踪位置以及出于其他更多组织原因,我还建议您稍微更改一下应用程序结构。

我认为当前结构的一个问题是 Layout 是每个页面组件的子组件。相反,我认为这个组件更适合作为您页面的父级,而不是让每个页面都呈现一个 Layout 组件。这同样适用于您的 Header 组件。

我建议将您的 App.js 文件更改为如下内容:

function App() {
  return (
    <ThemeProvider theme={theme}>
      <Header />
      <Layout>
        <Switch>
          <Route exact path="/" component={Start} />
          <Route exact path="/page-A" component={PageA} />
          <Route exact path="/page-B" component={PageB} />
          <Route exact path="/page-C" component={PageC} />
        </Switch>
      </Layout>
    </ThemeProvider>
  );
}

我也不认为每个屏幕都需要不同的 Menu 组件。

您可以改用通用 Menu 组件并在 Layout 组件内渲染此组件:

const Layout = (props) => {
  return (
    <React.Fragment>
      <Grid container>
        <Grid item xs={3} className="side-nav">
          <Menu />
        </Grid>
        <Grid item xs={9} className="main">
          <Box p={4}>{props.children}</Box>
        </Grid>
      </Grid>
    </React.Fragment>
  );
};

然后您可以将 Menu 组件更改为:

const pageLocations = ["/page-A", "/page-B", "/page-C"];
const pages = ["Page A", "Page B", "Page C"];

const Menu = () => {
  const location = useLocation();
  const [locations, setLocations] = React.useState([]);

  React.useEffect(() => {
    const currentPath = location.pathname;
    if (!locations.includes(currentPath)) {
      setLocations([...locations, currentPath]);
    }
  }, [location, locations, setLocations]);

  return (
    <Box>
      <MenuList>
        {pages.map((page, i) => {
          return (
            <MenuItem
              key={i}
              to={pageLocations[i]}
              className={locations.includes(pageLocations[i]) ? "" : "deactive"}
              component={NavLink}
            >
              {page}
            </MenuItem>
          );
        })}
      </MenuList>
    </Box>
  );
};

所以方法是跟踪之前从菜单访问过的所有页面。一个位置映射到每个菜单项,我们可以根据已经访问过的所有位置以及映射到菜单项的位置来检查是否应显示菜单项。

此答案不处理您从特定页面的 url 开始的情况,例如 /page-A 而不是 /


sandbox example