Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you get Material-UI Tabs to work with react-router?

I am trying to get Material-UI tabs to work with routing, and while the routing is working and displaying the selected tab, the smooth animation of navigating between tabs is no longer working. How can I use react router with Material-UI tabs to keep the tab animations working as they should?

As of now, I have the tabs in my HomeHeader.js and I am using this component to pass down the vale as props in order to change the value and thus change the selected tab.

For simplicity, I simplified my code to show the tabs I want to be linked.

Here is my code:

Header.js (Component with Tabs):

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)

Tab 1 Component (pass value into HomeHeader.js as props):

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

Tab 2 Component (pass value into HomeHeader.js as props):

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
like image 743
Colin Sygiel Avatar asked Nov 30 '22 21:11

Colin Sygiel


2 Answers

The way you are using Routes here are inefficient.

It should be Tabs are implemented in one place and only one place as this (simply no need to use HomeHeader in every page):

 <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>

as you can see tabs are asking for link and routes in the switch render compnents

for the animation I used this article: https://blog.logrocket.com/routes-animation-transitions-in-react-router-v4-9f4788deb964

here they are using react-addons-css-transition-group

please find the animation index.css file in demo

I wrapped pages from a HOC to make routing easier ( PageShell componet)

here is a working example:https://codesandbox.io/s/04p1v46qww

hope this will give you a head start

like image 117
Nadun Avatar answered Dec 04 '22 01:12

Nadun


To track active tab you can use location as tab value. And use router location as value for Tabs component. This way you achive change tabs animation out of box and highlight active tab when load page directly.

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>
        </>
    );
}
like image 44
Nikolay Zainchkovskiy Avatar answered Dec 04 '22 01:12

Nikolay Zainchkovskiy