【问题标题】:Use http path to set active tab使用 http 路径设置活动选项卡
【发布时间】:2021-11-15 10:26:43
【问题描述】:

我有这个垂直标签的例子:

import * as React from 'react';
import Tabs from '@mui/material/Tabs';
import Tab from '@mui/material/Tab';
import Typography from '@mui/material/Typography';
import Box from '@mui/material/Box';

interface TabPanelProps {
  children?: React.ReactNode;
  index: number;
  value: number;
}

function TabPanel(props: TabPanelProps) {
  const { children, value, index, ...other } = props;

  return (
    <div
      role="tabpanel"
      hidden={value !== index}
      id={`vertical-tabpanel-${index}`}
      aria-labelledby={`vertical-tab-${index}`}
      {...other}
    >
      {value === index && (
        <Box sx={{ p: 3 }}>
          <Typography>{children}</Typography>
        </Box>
      )}
    </div>
  );
}

function a11yProps(index: number) {
  return {
    id: `vertical-tab-${index}`,
    'aria-controls': `vertical-tabpanel-${index}`,
  };
}

export default function VerticalTabs() {
  const [value, setValue] = React.useState(0);

  const handleChange = (event: React.SyntheticEvent, newValue: number) => {
    setValue(newValue);
  };

  return (
    <Box
      sx={{ flexGrow: 1, bgcolor: 'background.paper', display: 'flex', height: 224 }}
    >
      <Tabs
        orientation="vertical"
        variant="scrollable"
        value={value}
        onChange={handleChange}
        aria-label="Vertical tabs example"
        sx={{ borderRight: 1, borderColor: 'divider' }}
      >
        <Tab label="Item One" {...a11yProps(0)} />
        <Tab label="Item Two" {...a11yProps(1)} />
        <Tab label="Item Three" {...a11yProps(2)} />
        <Tab label="Item Four" {...a11yProps(3)} />
        <Tab label="Item Five" {...a11yProps(4)} />
        <Tab label="Item Six" {...a11yProps(5)} />
        <Tab label="Item Seven" {...a11yProps(6)} />
      </Tabs>
      <TabPanel value={value} index={0}>
        Item One
      </TabPanel>
      <TabPanel value={value} index={1}>
        Item Two
      </TabPanel>
      <TabPanel value={value} index={2}>
        Item Three
      </TabPanel>
      <TabPanel value={value} index={3}>
        Item Four
      </TabPanel>
      <TabPanel value={value} index={4}>
        Item Five
      </TabPanel>
      <TabPanel value={value} index={5}>
        Item Six
      </TabPanel>
      <TabPanel value={value} index={6}>
        Item Seven
      </TabPanel>
    </Box>
  );
}

Sanbox:https://codesandbox.io/s/verticaltabs-material-demo-forked-cewtk?file=/demo.tsx

是否可以使用 url 链接来设置活动标签?例如:

http://localhost/tabs/one -> set tab 1 as active 
http://localhost/tabs/three -> set tab 3 as active 

我找到了这个示例https://reactrouter.com/web/example/nesting,但它看起来不适合我,因为我想继续使用 Tabs 组件。 Tabs 组件还有其他解决方案吗?

【问题讨论】:

  • 您可以通过使用 react 路由器的历史记录和位置,将 react 路由器与 tabs 组件一起使用。
  • 你能给我看一下代码示例吗?
  • 使用 url 支持更新您的代码和框示例。谢谢

标签: javascript reactjs material-ui react-material


【解决方案1】:

我已更新您的沙盒示例。在这两个文件中都进行了更改。首先让我们讨论一下demo.tsx的变化

Demo.tsx

首先,我从react-router-dom 导入了几个钩子

import { useHistory, useLocation } from "react-router-dom";

添加了一个 util 函数,用于根据 url 路径获取活动选项卡。

function getNumber(location: string) {
  const pathname = location.split("/")[2];
  if (!pathname) return 0;
  else {
    switch (pathname) {
      case "two":
        return 1;
      case "three":
        return 2;
      case "four":
        return 3;

      default:
        return 0;
    }
  }
}

然后状态和挂钩初始化。初始状态还会检查 url 并根据组件挂载上的 url 参数激活相关选项卡。

const history = useHistory();
const location = useLocation();
const [value, setValue] = React.useState(getNumber(location?.pathname));

更改了基于索引更新选项卡的handleChange 函数。它现在不是更新选项卡的状态值,而是根据选项卡索引推送新的 url。

const handleChange = (event: React.SyntheticEvent, newValue: number) => {
history.push(
  `/${
    newValue === 1
      ? "tabs/two"
      : newValue === 2
      ? "tabs/three"
      : newValue === 3
      ? "tabs/four"
      : "tabs/one"
    }`
  );
};

由于在上面的handleChange 函数中,value 没有被更新,这实际上是控制活动选项卡,我将该代码移动到 useEffect 挂钩,并依赖于 location 对象。每当位置更改时,这将自动更新相关选项卡。状态变化移动到useEffect来处理场景,当用户按下返回键回到上一个标签页时,我们可以根据location变化更新value状态。

React.useEffect(() => {
  setValue(getNumber(location?.pathname));
}, [location]);

Index.tsx的变化

react-router-dom 导入一些组件来管理url导航。

import { BrowserRouter as Router, Switch, Route } from "react-router-dom";

比将整个应用程序代码移动到Router 中,这样,所有组件都可以访问路由器。

<Router>
  <StyledEngineProvider injectFirst>
    <Switch>
      <Route exact path="/tabs/:tab?" component={Demo} />
      <Route exact path="/" component={Demo} />
    </Switch>
  </StyledEngineProvider>
</Router>

这是更新后的codesandbox link

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-09
    • 1970-01-01
    • 2013-07-24
    • 2018-03-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多