Rabin Limbu
Rabin Limbu

Reputation: 23

React Router not working as expected when using withStyles

I did a quick search and couldn't find related solution in stackoverflow but if I missed please direct me there and sorry for the duplication.

My problem is react router not working as expected when using withStyles. When you click "Home" link twice it shows blank page the second time. If I don't use "withStyles" and export it normally than it works as expected.

Thank you so much in advance for answering.

Please see code below. Basically other 2 files for "Contact" and "About" are same as Home only the name difference.

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import './css/index.css';
import App from './components/App';
import * as serviceWorker from './serviceWorker';
import { history } from './store';


ReactDOM.render((
  <Router history={history}>
    <App/>
  </Router>),
document.getElementById('root'));

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
serviceWorker.unregister();

App.js

import React, { Component } from 'react';
import { BrowserRouter as Router, Route, Switch, Link } from 'react-router-dom';
import Contact from './Contact';
import About from './About';
import Home from './Home';
import Header from './Header';
import '../css/App.css';


class App extends Component {
  render() {
    return (
        <div>
            <Header/>
            <Switch>
                <Route exact path="/" component={Home} />
                <Route path="/about" component={About} />
                <Route path="/contact" exact component={Contact} />
                <Route component={Error} />
            </Switch>
        </div>
    );
  }
}

export default App;

Header.js

import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import { makeStyles, withStyles } from '@material-ui/core/styles';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import Typography from '@material-ui/core/Typography';

const useStyles = makeStyles(theme => ({
  root: {
    flexGrow: 1,
  },
  menuButton: {
    marginRight: theme.spacing(2),
  },
  title: {
    flexGrow: 1,
  },
  link: {
    margin: theme.spacing(1),
  }
}));


class Header extends Component {
  render() {
      const classes = this.props;

      return (
        <div>
            <ul>
                <li>
                    <Link to="/">Home</Link>
                </li>
                <li>
                    <Link exact to="/about">About</Link>
                </li>
                <li>
                    <Link exact to="/contact">Contact</Link>
                </li>
            </ul>
        </div>
      );
  }
}

export default withStyles(useStyles)(Header);

Home.js

import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import { makeStyles, withStyles } from '@material-ui/core/styles';
import Paper from '@material-ui/core/Paper';
import Typography from '@material-ui/core/Typography';
import PropTypes from 'prop-types';
import { withRouter } from 'react-router-dom';

const useStyles = makeStyles(theme => ({
  root: {
    padding: theme.spacing(3, 2),
  },
}));


class Home extends Component {
    constructor(props) {
        super(props);
        this.state = {
        };
    }

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

    return (
            <div>
              <Paper className={classes.root}>
                <Typography variant="h5" component="h3">
                  This is Home page
                </Typography>
              </Paper>
            </div>
        );
    }
}

Home.propTypes = {
    classes: PropTypes.object.isRequired
};

//just so you know I have used with both withRouter and without and its the same with 
//both 

//const HomeWithRouter = withRouter(Home);
//export default withStyles(useStyles)(HomeWithRouter);
export default withStyles(useStyles)(Home);

Upvotes: 0

Views: 540

Answers (2)

Dan Lee
Dan Lee

Reputation: 720

As mentioned by Jake, makeStyles is a hook, and

You can’t use Hooks inside of a class component.

refer to: https://reactjs.org/docs/hooks-faq.html#should-i-use-hooks-classes-or-a-mix-of-both

I believe using hooks can make code more concise than class component, you can write your Home component below as hooks instead:

import React, { Component } from "react";
import { Link } from "react-router-dom";
import { makeStyles, withStyles } from "@material-ui/core/styles";
import Paper from "@material-ui/core/Paper";
import Typography from "@material-ui/core/Typography";
import PropTypes from "prop-types";
import { withRouter } from "react-router-dom";

const useStyles = makeStyles(theme => ({
  root: {
    padding: theme.spacing(3, 2)
  }
}));

const Home = props => {
  const [state, setState] = React.useState({});
  const classes = useStyles();

  return (
    <div>
      <Paper className={classes.root}>
        <Typography variant="h5" component="h3">
          This is Home page
        </Typography>
      </Paper>
    </div>
  );
};

Home.propTypes = {
  classes: PropTypes.object.isRequired
};

export default Home;

Upvotes: 0

Jake Luby
Jake Luby

Reputation: 1758

makeStyles is a hook for functional components, you are using class components with an HOC.

Change

const useStyles = makeStyles(theme => ({
  root: {
    padding: theme.spacing(3, 2),
  },
}));

to

const styles = theme => ({
  root: {
    padding: theme.spacing(3, 2),
  },
});

And then change

export default withStyles(useStyles)(Home);

to

export default withStyles(styles)(Home);

Do that for both your Home and your Header components. In all honesty though, I'd probably just convert the class to a functional component with hooks instead, but either way you have to either use hooks or classes, but can't mix the two.

Upvotes: 1

Related Questions