如何获得Material-UI选项卡以与react-router一起使用?

时间:2018-07-10 04:47:07

标签: javascript reactjs react-router material-ui react-router-dom

我正在尝试使Material-UI选项卡能够与工艺路线一起使用,并且当工艺路线正在工作并显示所选选项卡时,在选项卡之间导航的流畅动画不再起作用。如何将React Router与Material-UI标签一起使用,以使标签动画保持应有的状态?

截至目前,我的HomeHeader.js中具有选项卡,并且我正在使用此组件将vale作为道具传递,以更改值并由此更改所选的选项卡。

为简单起见,我简化了代码以显示要链接的标签。

这是我的代码:

Header.js(带有标签的组件):

import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { Link } from 'react-router-dom'

class HomeHeader extends Component {

  state = {
    value: false
  };

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

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

    return (
        <AppBar className={classes.appBar} elevation={this.props.elevation}>
          <Hidden smDown>
            <Grid container justify="space-between" alignItems="center">
              <Tabs value={value} onChange={this.handleChange}>
                <Tab label="monitor" component={Link} to="/monitor" />
                <Tab label="sensor" component={Link} to="/sensor" />
              </Tabs>
            </Grid>
          </Hidden>
        </AppBar>
    )
  }
}

export default withStyles(styles)(HomeHeader)

标签1组件(将值作为道具传递给HomeHeader.js):

import React from 'react'

import HomeHeader from '../components/HomeHeader'

class SensorProductPage extends React.PureComponent { // eslint-disable-line react/prefer-stateless-function

  render() {
    return (
      <div>
        <HomeHeader value={1} />
        <div> Hello </div>
      </div>
    );
  }
}

export default SensorProductPage

标签2组件(将值作为道具传递给HomeHeader.js):

import React from 'react'

import HomeHeader from '../components/HomeHeader'

class MonitorProductPage extends React.PureComponent {

  render() {
    return (
      <div>
        <HomeHeader value={0} />
        <div> Hello </div>
      </div>
    );
  }
}

export default MonitorProductPage

3 个答案:

答案 0 :(得分:3)

要跟踪活动的选项卡,可以将位置用作选项卡值。并将路由器位置用作“选项卡”组件的值。这样,您就可以立即打开更改标签的动画,并在直接加载页面时突出显示活动标签。

export const Module: React.FC<IModuleProps> = props => {
    const match = useRouteMatch();
    const location = useLocation();

    return (
        <>
            <Tabs value={location.pathname} >
                <Tab label="Dashboard" component={Link} to={`${match.url}/dashboard`} value={`${match.url}/dashboard`} />
                <Tab label="Audit Results" component={Link} to={`${match.url}/audit-results`} value={`${match.url}/audit-results`} />
            </Tabs>
            <Switch>
                <Route path={`${match.url}/dashboard`}>
                    <Dashboard />
                </Route>
                <Route path={`${match.url}/audit-results`}>
                    <AuditResults />
                </Route>
                <Route path={`${match.url}`}>
                    <Dashboard />
                </Route>
            </Switch>
        </>
    );
}

答案 1 :(得分:2)

您在此处使用路由的方式效率低下。

应该将Tabs放在一个地方,并且只有一个地方(这样就不需要在每个页面中使用HomeHeader):

 <BrowserRouter>
    <div className={classes.root}>
      <AppBar position="static" color="default">
        <Tabs
          value={this.state.value}
          onChange={this.handleChange}
          indicatorColor="primary"
          textColor="primary"
          fullWidth
        >
          <Tab label="Item One" component={Link} to="/one" />
          <Tab label="Item Two" component={Link} to="/two" />
        </Tabs>
      </AppBar>

      <Switch>
        <Route path="/one" component={PageShell(ItemOne)} />
        <Route path="/two" component={PageShell(ItemTwo)} />
      </Switch>
    </div>
  </BrowserRouter>

如您所见,标签在开关渲染组件中要求链接和路由

对于动画我使用了这篇文章:https://blog.logrocket.com/routes-animation-transitions-in-react-router-v4-9f4788deb964

他们在这里使用 react-addons-css-transition-group

请在演示中找到动画index.css文件

我从HOC包装页面以简化路由(PageShell组件)

这是一个有效的示例:https://codesandbox.io/s/04p1v46qww

希望这会给您一个良好的开端

答案 2 :(得分:1)

对于上面的当前结构,您可以看到随着路线的更改,“标签”正在重新呈现。

反应的方式是由持有组件的组件构建的,因此,如果更改一个组件,则将渲染其所有子组件。

因此,在您的情况下,这就是组件的结构方式:

MainApp >
          Route('monitor') > MonitorProductPage > HomeHeader
          Route('sensor') > SensorProductPage > HomeHeader

在此示例中,您可以看到,当您更改路线时,您将更改所有内容,并且需要重新呈现新的HomeHeader

我将对它进行结构化,以确保HomeHeader将被创建一次,并且仅道具会发生变化。 (出于性能和此处的问题) 就像这样:

MainApp >
          Route('innerpage/*') > InnerPage > 

               > MonitorProductPage
               > SensorProductPage

像React Router dom中的这段代码 https://reacttraining.com/react-router/web/example/route-config

这意味着您只有一条路线可以捕获这些内部页面,就像上面那样,或者捕获所有(*) 然后,您将在InnerPage内部拥有另一个路由器,该路由器将决定显示哪个页面。

const routes = [
{
    path: "/innerpage",
    component: InnerPage
  },
  {
    path: "/monitor",
    component: MonitorProductPage,
  },
  {
    path: "/sensor",
    component: SensorProductPage
  }
];

和组件“ InnerPage”将呈现HomeHeader,并且内部将具有决定其“主体”的路由器