如何以编程方式从Material UI设置Tab中的活动选项卡

问题描述 投票:3回答:3

我正在使用Material UI和React,我正在以编程方式创建多个选项卡,如下所示:

return (
    <div>
        <Tabs>
            {this.state.elements.map(elem => {
                return (
                    <Tab key={elem.elemID} label={elem.name} >
                        <div>
                           // rest removed for brevity
                        </div>
                    </Tab>
                )
            })}
        </Tabs>
    </div>
);

这是有效的,并且显示选项卡,但问题是默认情况下,当组件呈现时,第一个选项卡是活动选项卡。然而,我想根据我从道具获得的id值以编程方式设置活动选项卡。所以基本上,如果this.props.selectedID === elem.elemID然后我希望该选项卡是组件呈现时的活动选项卡。当然,一旦呈现组件,用户应该可以自由地单击并在选项卡之间切换。知道如何实现它吗?

reactjs material-ui
3个回答
2
投票

valueTabs上使用Tab prop使其成为受控组件:

<Tabs value={this.props.selectedID}>
    {this.state.elements.map(elem => {
            return (
                <Tab key={elem.elemID} label={elem.name} value={elem.elemID}>
                    <div>
                       // rest removed for brevity
                    </div>
                </Tab>
            )
        })}
</Tabs>

0
投票

TL DR;假设您正在尝试将其映射到URL,这里的技巧是以编程方式将<Tab>的“value”属性设置为URL当前具有的属性。我假设你正在使用React Router

例:

const baseUrls = ['', 'online-manga-reader', 'admin'];

class TabBar extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      value: this.processPathName(),
    };
  }

  processPathName(){
    const path = this.props.location.pathname.split('/')[1];
    const value =  baseUrls.indexOf(path);
    return value !== -1 ? value : 0; // This is the default one.
  }

  handleChange = (event, value) => {
    this.setState({ value });
    this.returnTabContainer(value);
  }

  returnTabContainer(value) {

    switch (value) {
      case 1:
        this.props.history.push('/online-manga-reader');
        break;
      case 2:
        this.props.history.push('/admin/article');
        break;
      default:
        this.props.history.push('/');
    }
  }

  returnTabAdmin() {
    return this.props.isAdmin ? <Tab label="Admin Tab" /> : '';
  }

  render() {
    const { classes } = this.props;
    const { value } = this.state;

    return (
      <div className={classes.root}>
        <AppBar position="static">
          <Tabs 
            value={value} 
            onChange={(evt, val) => {this.handleChange(evt, val); }}
          >
            <Tab label="Home" />
            <Tab label="Online Manga Reader" />
            {this.returnTabAdmin()}
          </Tabs>
          <LoginButton />
        </AppBar>
      </div>
    );
  }
}
export default connect(mapStateToProps)(withStyles(styles)(withRouter(TabBar)));

说明

const baseUrls = ['', 'online-manga-reader', 'admin'];

这是一个位于类外部的数组,它包含URL的第一个路径(或基本URL):

这将匹配基本URL(因此将选择第一个)http://example.com/

这一个,第二个将匹配

第三个: - http://example.com/admin - http://example.com/admin/article/create

我在这里使用的“技巧”在于processPathName()方法。它从React-Router读取当前的URL,然后调用split,它已经在所需的部分中解析了你的URL:

http://example.com/admin/article/create 

将翻译为:

/ admin article create

总是让我们回到1这个我们正在寻找的位置(这是分裂中的一个)。

有了它,我们使用好的'indexOf来搜索数组内部的路径。如果找到它,它将返回与我们的选项卡位置匹配的数字。这就是为什么它们按照相同的顺序排列是很重要的。

如果它没有找到它,我们设置一个默认值(在这种情况下,我们将其设置为零,这将占主页)。

您的商品应该正常呈现,没有任何问题。


0
投票

这是我的答案,作为钩子的最小通用示例。我还假设你使用的是React Router。它实际上将url状态链接到Tab的'selectedness'(在更改和渲染时):

const NavTabs = ({ history, location }) => {
  function getInitialTab() {
    switch (true) {
      case /\/componentone/.test(location.pathname):
        return 0
      case /\/componenttwo/.test(location.pathname):
        return 1
      default:
        return 0
    }
  }

  const [value, setValue] = useState(getInitialTab())

  function handleChange(event, val) {
    setValue(val)
    switch (val) {
      case 0:
        history.push('/componentone')
        break
      case 1:
        history.push('/componenttwo')
        break
      default:
        break
    }
  }

  return (
    <NoSsr>
      <div>
        <AppBar position="static">
          <Tabs
            variant="fullWidth"
            value={value}
            onChange={handleChange}
          >
            <Tab label="Component One" />
            <Tab label="Component Two" />
          </Tabs>
        </AppBar>
        {value === 0 && (
          <Typography component="div">
            <ComponentOne history={history} location={location} />
          </Typography>
        )}
        {value === 1 && (
          <Typography component="div">
            <ComponentTwo history={history} location={location} />
          </Typography>
        )}
      </div>
    </NoSsr>
  )
}
© www.soinside.com 2019 - 2024. All rights reserved.