question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

using v4() on key property breaking styles

See original GitHub issue

Type of problem: bug?

Using a uuid as a key value looks to break the material-ui-styles. It seems material-ui is relying on an incrementing counter when using a key property in the component hierarchy.

For example, using v4() uuid in the following code breaks the material-ui styles:

import React from 'react';
import PropTypes from 'prop-types';
import {MenuList, MenuItem} from 'material-ui/Menu';
import Paper from 'material-ui/Paper';
import {withStyles} from 'material-ui/styles';
import {ListItemIcon, ListItemText} from 'material-ui/List';
import DraftsIcon from '@material-ui/icons/Drafts';
import SendIcon from '@material-ui/icons/Send';
import {NavLink} from 'react-router-dom';
import {connect} from 'react-redux'
import { withRouter } from 'react-router';
import {v4} from 'uuid';
import classNames from 'classnames';

const styles = theme => ({
  menuItem: {
    '&:focus': {
      backgroundColor: theme.palette.primary.main,
      '& $primary, & $icon': {
        color: theme.palette.common.white
      }
    }
  },
  primary: {},
  icon: {}
});

function Navigation(props) {
  const {classes} = props;
  console.log('Navigation',props)

  return (<Paper>
    <MenuList>
      <NavLink to="/" className={props.classes.removeUnderline}>
        <MenuItem className={classes.menuItem}>
          {/* <ListItemIcon className={classes.icon}>
            <SendIcon/>
          </ListItemIcon> */}
          <ListItemText classes={{
              primary: classes.primary
            }} inset={true} primary="Home"/>
        </MenuItem>
      </NavLink>
      {props.services.map( s =>
        <NavLink to={s.urlPattern} className={classNames(props.classes.removeUnderline)} key={v4()}>
          <MenuItem className={classNames(classes.menuItem)}>
            {/* <ListItemIcon className={classes.icon}>
              <SendIcon/>
            </ListItemIcon> */}
            <ListItemText classes={{
                primary: classes.primary
              }} inset={true} primary={s.headerTitle}/>
          </MenuItem>
        </NavLink>
      )}
    </MenuList>
  </Paper>);
}

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

Navigation = withStyles(styles)(Navigation);

export default withRouter(connect((state) => ({services: state.onshoreApp.services, isFetching : state.onshoreApp.isFetching}))(Navigation))

Changing the key property to use an incrementing counter instead fixes the styles.

import React from 'react';
import PropTypes from 'prop-types';
import {MenuList, MenuItem} from 'material-ui/Menu';
import Paper from 'material-ui/Paper';
import {withStyles} from 'material-ui/styles';
import {ListItemIcon, ListItemText} from 'material-ui/List';
import DraftsIcon from '@material-ui/icons/Drafts';
import SendIcon from '@material-ui/icons/Send';
import {NavLink} from 'react-router-dom';
import {connect} from 'react-redux'
import { withRouter } from 'react-router';
import {v4} from 'uuid';
import classNames from 'classnames';

const styles = theme => ({
  menuItem: {
    '&:focus': {
      backgroundColor: theme.palette.primary.main,
      '& $primary, & $icon': {
        color: theme.palette.common.white
      }
    }
  },
  primary: {},
  icon: {}
});

function Navigation(props) {
  const {classes} = props;
  console.log('Navigation',props)

  return (<Paper>
    <MenuList>
      <NavLink to="/" className={props.classes.removeUnderline}>
        <MenuItem className={classes.menuItem}>
          {/* <ListItemIcon className={classes.icon}>
            <SendIcon/>
          </ListItemIcon> */}
          <ListItemText classes={{
              primary: classes.primary
            }} inset={true} primary="Home"/>
        </MenuItem>
      </NavLink>
      {props.services.map( (s,i) =>
        <NavLink to={s.urlPattern} className={classNames(props.classes.removeUnderline)} key={i}>
          <MenuItem className={classNames(classes.menuItem)}>
            {/* <ListItemIcon className={classes.icon}>
              <SendIcon/>
            </ListItemIcon> */}
            <ListItemText classes={{
                primary: classes.primary
              }} inset={true} primary={s.headerTitle}/>
          </MenuItem>
        </NavLink>
      )}
    </MenuList>
  </Paper>);
}

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

Navigation = withStyles(styles)(Navigation);

export default withRouter(connect((state) => ({services: state.onshoreApp.services, isFetching : state.onshoreApp.isFetching}))(Navigation))

The styles that are breaking in this case is the background color of my navigation items:

how it looks with key={v4()}: screen shot 2018-04-21 at 7 40 47 am

renders correctly using an incrementing counter key={i}: screen shot 2018-04-21 at 7 39 23 am

Tech Version
Material-UI 1.0.0-beta.42
React 16.2.0
browser any
etc

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
oliviertassinaricommented, Apr 20, 2018

@Gribbs I was able to reproduce your issue in https://codesandbox.io/s/j7yjj1l9mw. This is a react question. When a link is pressed. It gets the CSS active state. The active state change the background color. Clicking a link also triggers a rerender. Given you are using key={v4()}, you will inject a new dom node at each render, losing the active state and the background color.

⚠️ I fear you have set yourself a bad track record. Don’t expect us from answering your question in the future here. We will close them.

capture d ecran 2018-04-21 a 00 57 30

0reactions
Gribbscommented, Apr 21, 2018

“Given you are using key={v4()}, you will inject a new dom node at each render”. Unless I’m missing something, it renders exactly the same amount of times whether I use key={i} or key={v4()} and there’s no extra dom nodes created? When I changed your example to use the array key it worked as expected https://codesandbox.io/s/mjly8xk52x !

Read more comments on GitHub >

github_iconTop Results From Across the Web

using v4() on key property breaking styles #11084 - GitHub
Type of problem: bug? Using a uuid as a key value looks to break the material-ui-styles. It seems material-ui is relying on an...
Read more >
Migrating to v5: getting started - Material UI - MUI
This guide explains how and why to migrate from Material UI v4 to v5. ... will automatically address many of the breaking changes...
Read more >
Property accessors - JavaScript - MDN Web Docs - Mozilla
Property accessors provide access to an object's properties by using the dot notation or the bracket notation.
Read more >
Style Props - Chakra UI
Learn how to use style props in Chakra UI. ... The following table shows a list of every style prop and the properties...
Read more >
Upgrade Guide - Tailwind CSS
Tailwind CSS v3.0 is a major update to the framework with a brand new internal engine and as such includes a small number...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found