React Material UI + Router redirect button

13,470

Solution 1

The easier way is to pass the react-router-dom Link to the component property of the Material UI button:

    import React, { useState } from 'react';
    import { Link } from 'react-router-dom';
    import Button from '@material-ui/core/Button';

    ...

    <Button component={Link} to="/some-route" color="primary">
      MyButton
    </Button>

    // OR

    const MyLink = props => <Link to="/some-route" {...props} />

    <Button component={MyLink} color="primary">
      MyButton
    </Button>

Material UI example: https://material-ui.com/demos/buttons/#third-party-routing-library

Solution 2

For those using Fraction's solution but running into error Error: Invariant failed: You should not use <Link> outside a <Router>, the solution is to wrap whatever custom element Link is used in in a BrowserRouter, e.g.

// App.js

...

<BrowserRouter>
   CustomElement
</BrowserRouter>
//CustomElement.js

...

return (
    <Button component={Link} to="/some-route" color="primary">
      MyButton
    </Button>
)
Share:
13,470
Maramal
Author by

Maramal

Updated on June 08, 2022

Comments

  • Maramal
    Maramal almost 2 years

    I am trying to use Material-UI for React but I am not sure about the proper way to redirect to other pages / components.

    I have read several sites about the different ways to redirect using react-router-dom, but still, I don't get the "final" way.

    history.push:

    One of the ways that didn't work for me was using props.history.push('/some-route'). I get that history is undefined. I also tried accesing it through props.history:

    import React, { Fragment } from 'react';
    import { Button } from '@material-ui/core';
    
    const Page = props => {
        const { history } = props;
    
        return (
            <Fragment>
                <Button
                    variant="contained"
                    color="primary"
                    size="large"
                    onClick={() => history.push('/some-route')}
                >My Button</Button>
            </Fragment>
        );
    };
    
    export default Page;
    

    Redirect Component

    Another way that didn't work for me was using the same react-router-dom Redirect component. Here I don't get any error, it just does nothing when clicking:

    import React, { Fragment } from 'react';
    import { Button } from '@material-ui/core';
    import { Redirect } from 'react-router-dom';
    
    const Page = props => {
        const { history } = props;
    
        return (
            <Fragment>
                <Button
                    variant="contained"
                    color="primary"
                    size="large"
                    onClick={() => <Redirect to={'/some-route'} />}
                >My Button</Button>
            </Fragment>
        );
    };
    
    export default Page;
    

    Links with styles

    I have found the only way that is still working with react-router-dom Link Components where I pasted the same generated classes names:

    import React, { Fragment } from 'react';
    import { Link } from 'react-router-dom';
    
    const Page = props => {
        return (
            <Fragment>
                <Link
                    class="MuiButtonBase-root-124 MuiButton-root-98 MuiButton-contained-109 MuiButton-containedPrimary-110 MuiButton-raised-112 MuiButton-raisedPrimary-113 MuiButton-sizeLarge-122"
                    to="/some-route"
                >My Button</Button>
            </Link>
        );
    };
    
    export default Page;
    

    And the last one that I didn't even try since I guess it's wrong is inserting a Button component inside a Link component (or viceversa).

    Which way do you recommend to redirect when clicking a button? Any comments are appreciated.

  • AMS777
    AMS777 about 3 years
    Documentation about the component property: material-ui.com/guides/composition/#component-prop