简体   繁体   中英

Create separate state for each component created dynamically with same handler

I have a React component created with Material UI and the child component ( Paper ) is dynamically generated based on the number of items of an array.

I have to change the elevation property of the hovered Paper, to distinguish it from the others.

In the real application, I don't know the number of items of the array, so I must use only one event handler for mouseover and mouseout , but I can't find a way to apply the effect only to the item hovered, it´s getting applied to all of them. How can I fix this?

Here's my code (I'm using React Hooks)

import React, { useState } from 'react'
import Paper from '@material-ui/core/Paper';
import Grid from '@material-ui/core/Grid';
import { makeStyles } from '@material-ui/core/styles';

const useStyles = makeStyles(theme => ({
    container : {
        backgroundColor: '#f5f5f5',
        padding: theme.spacing(2),  
    },
    paper: {
      padding: theme.spacing(2),         
    },
  }));

const List = () => {     
    const classes = useStyles();  
    const [elevation, setElevation] = useState(1);
    const items = ['a','b'];

    const paperHandleMouseOver = (evt) => {
        setElevation(4);
    }

    const paperHandleMouseOut = (evt) => {
        setElevation(1);
    }

    return(   
        <div className={classes.container}>
            <Grid container spacing={3}>
                {
                    items.map(item => 
                        <Grid item xs={12}>
                            <Paper elevation={elevation} onMouseOver={paperHandleMouseOver} onMouseOut={paperHandleMouseOut} className={classes.paper}>Test{item}</Paper>
                        </Grid>
                    )
                }                
            </Grid>  
        </div>           
    )
}

export default List

Thanks in advance

You could try keeping track of the index of the hovered paper instead of the elevation and use it to toggle the value like this:

const List = () => {     
  const classes = useStyles();  
  // const [elevation, setElevation] = useState(1); // don't need to use this anymore
  const [selected, setSelected] = useState(); // New state to track hovered
  const items = ['a','b'];

  // notice the extra '() =>' needed to pass in the index
  const paperHandleMouseOver = (i) => (evt) => {
    //setElevation(4);
    setSelected(i);
  }

  const paperHandleMouseOut = (evt) => {
    //setElevation(1);
    setSelected(null);
  }

  return(   
    <div className={classes.container}>
      <Grid container spacing={3}>
        {items.map((item, i) => 
          <Grid item xs={12}>
            <Paper 
              elevation={i === selected ? 4 : 1} // if selected elevate 4 else 1
              onMouseOver={paperHandleMouseOver(i)} // pass the index
              onMouseOut={paperHandleMouseOut} // dont need the index, just unset
              className={classes.paper}>
                Test{item}
            </Paper>
          </Grid>
        )}                
      </Grid>  
    </div>           
  )
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM