Search code examples
reactjsmaterial-uiaccordiononchangemap-function

why is handleChange function applied to all the elements being mapped in react?


I am using accordion from mui where I am using map() function to add data to each accordion. For onChange event of a particular accordion, handleChange is be called because of which that accordion should expand, but all the accordions are been expanded rather than the one for which the handleChange is called! How to fix this?

Code for handle change:

  const [expanded, setExpanded] = React.useState('panel1');

  const handleChange = (panel) => (event, newExpanded) => {
    console.log(panel);
    setExpanded(newExpanded ? panel : false);
  };

Code returned inside react component:

   <Container sx={{ paddingBlock: "4rem" }}>
      {faqData.map((faq, index) =>
        <Accordion key={index} expanded={expanded === ('panel' + { index })} onChange={handleChange('panel' + { index })}>
          <AccordionSummary aria-controls={('panel' + { index } + 'd - content')} id={('panel' + { index } + 'd-header')}>
            <Typography>{faq[0]}</Typography>
          </AccordionSummary>
          <AccordionDetails>
            <Typography>
              {faq[1]}
            </Typography>
          </AccordionDetails>
        </Accordion>
      )}
    </Container>

Solution

  • The problem is in the way you construct the expression for the expanded property as well as the argument to the handleChange function.

    What happens is that 'panel' + {index} evaluates to 'panel[object Object]' string, the same for all panels.

    You can achieve the desired result by using string interpolation instead:

            <Accordion
              key={index}
              expanded={expanded === `panel${index}`}
              onChange={handleChange(`panel${index}`)}
            >
    

    You can see a live demo in this Stackblitz project.