8

I have this code:

            <Drawer 
                docked = {false}
                width = {330}
                open = {this.state.drawerOpen}
                onRequestChange = {(drawerOpen) => this.setState({drawerOpen})}
            >

                    <MenuItem primaryText="Inicio" onTouchTap = {this.drawerOpened} containerElement = {<Link to="/administrador/inicio"/>}/>
                    <MenuItem primaryText="Nueva Incidencia" onTouchTap = {this.drawerOpened} containerElement = {<Link to="/administrador/nueva_incidencia"/>}/>
                    <MenuItem primaryText="Incidencias Recibidas" onTouchTap = {this.drawerOpened} containerElement = {<Link to="/administrador/incidencias_recibidas"/>}/>
                    <MenuItem primaryText="Informes" /*onTouchTap = {() => this.currentPages('Informes')}*/onTouchTap = {this.drawerOpened} containerElement = {<Link to="/administrador/informes"/>}/>
            </Drawer>

I want that when I click on one MenuItem, it set up as 'active' (as in Bootstrap), with a background lighgrey and similar styles. How could I do this?. The problem is due to React-Router too, which unmount the component Menu and Re-Render it again, so states are not available.

Thank you.

JuMoGar
  • 1,740
  • 2
  • 19
  • 46

6 Answers6

9

In more recent version of Material UI (for sure in v4) you can use the selected property, for example this is my <ListItemLink> component, I'm using ListItem components but works also with MenuItem. Notice that line at selected={to === location.pathname}:

import PropTypes, { InferProps } from 'prop-types'
import React from 'react'
import { Link, useParams, useLocation } from 'react-router-dom'

function ListItemLink({ disabled = false, icon, primary, to }: InferProps<typeof ListItemLink.propTypes>) {
  const location = useLocation()

  const renderLink = React.useMemo(
    () => React.forwardRef<HTMLAnchorElement>((itemProps, ref) => <Link to={to} ref={ref} {...itemProps} />),
    [to],
  )

  return (
    <ListItem
      button
      selected={to === location.pathname}
      disabled={disabled ?? false}
      component={renderLink}
    >
      {icon ? <ListItemIcon>{icon}</ListItemIcon> : null}
      <ListItemText primary={primary} />
    </ListItem>
  )
}

ListItemLink.propTypes = {
  icon: PropTypes.element,
  primary: PropTypes.string.isRequired,
  to: PropTypes.string.isRequired,
  disabled: PropTypes.bool
}

ListItemLink.defaultProps = {
  disabled: false
}

And if, at some point, you want to customize the default selected style, just override it when creating the theme:

import { createMuiTheme } from '@material-ui/core/styles'
import { colors } from '@material-ui/core'


const theme = createMuiTheme({
  overrides: {
    MuiListItem: {
      root: {
        "&$selected": {
          color: colors.blue[500],
          backgroundColor: colors.lightBlue[100]
        }
      }
    }
  }
})

export default theme
Luca Faggianelli
  • 2,032
  • 20
  • 23
5

Here is my workaround:

define function:

isActive = (value) => (location.pathname === value ? 'active' : '')

<MenuItem primaryText="Inicio" onTouchTap = {this.drawerOpened} 
className={this.isActive('/administrador/inicio')}
containerElement = {<Link to="/administrador/inicio"/>}/>

now you are just missing de css styles for 'active'.

jpnazar
  • 81
  • 1
  • 6
0

How about creating a wrapper component around MenuItem and accepting style property and then applying it to MenuItem?

This may help further: Toggle background color of list on click react.js

Community
  • 1
  • 1
TechTurtle
  • 2,667
  • 4
  • 22
  • 31
  • thank you a lot. I have already seen this. But my problem is too due to I am using Routes Link from React Router, and the component re-render losing his states. – JuMoGar Apr 25 '17 at 19:10
  • ohh, didn't know that as was not mention. I suggest if you can post a separate question to handle state using React Router re-rendering. – TechTurtle Apr 25 '17 at 19:23
  • States are not available due to the unmount and re-rendering component, they are setted up as default. However, I only have a state: opened: true/false, no more. Thank you. – JuMoGar Apr 26 '17 at 12:51
0

@jpnazar answer is almost correct. However, the containerElement properties is no longer working. you can now use the code above to specify the link.

import { Link } from 'react-router-dom';
import MenuItem from '@material-ui/core/MenuItem';

...

<MenuItem component={Link} to="/your-path">...</MenuItem>

check out the issue on. https://github.com/mui-org/material-ui/issues/204

0

I am not sure if material UI already has an existing param with which we can set an active state. But instead, I found this workaround and it works like charm <ListItem key={item} sx={{ display: 'block', color: '#9A77CF', ...(window.location.pathname === "/selected pathname" && { backgroundColor: "#9A77CF", color: "#FFF", stroke: "#FFF"})}} >

0

Use the pathname information to determine if the item matches the current route:

const { pathname } = useLocation();
<List>

   <ListItem component={Link} to={"/about"} selected={"/about" === pathname}>

          <ListItemText primary={"About"} />

    </ListItem>

</List>
Muh-Osman
  • 159
  • 1
  • 5