skip to Main Content

So I have the following code:

const test = (e) => {
  console.log('example:', e.target.item.attributes.dataIWant);
}

{records.map((item, index) => {

        return (
          <>
            <Accordion key={index}>
              <AccordionSummary  onClick={test(item)} expandIcon={<ExpandMoreIcon />} aria-controls="panel1a-content" id="panel1a-header">
                <Typography>{item.attributes.name} {item.attributes.date}</Typography>
              </AccordionSummary>
            </Accordion>
          </>
        )
      })}

This is using react material UI, I have a collection of data in records, that I am mapping through. This creates and accordion panel that you can click to see accordion details.

When i click one of those panels, i want to grab a specific piece of data from the data set. Lets call it item.attributes.id

Generally i would assume to grab it with the event, to target that specific panels click/data set. But it doesn’t seem to be working, just getting item is undefined.

So what am I missing here?

2

Answers


  1. When you wrote onClick={test(item)} I interpret that the return value of the test() function is assinged to the onClick prop, during the component render.

    During rendering, the function doesn’t return anything explicitly (we get undefined implicitly). Therefore, your code becomes onClick={undefined}. But we want the test function to be executed, whenever the <AccordianSummary/> is clicked.

    const test = (event, itemId) => {
      console.log(itemId);
    }
    
    {records.map((item, index) => {
      return (
        <Accordion key={index}>
          <AccordionSummary
            onClick={(event) => test(event, item.attributes.id)}
            expandIcon={<ExpandMoreIcon />}
            aria-controls="panel1a-content"
            id="panel1a-header"
          >
            <Typography>{item.attributes.name} {item.attributes.date}</Typography>
          </AccordionSummary>
        </Accordion>
      )
    })}
    

    To achieve this expected output, a function reference has to be passed to onClick, that will be called later, and not during the rendering process. I’d suggest to user an arrow function

    (event) => test(event, item.attributes.id)

    This arrow function will be invoked when the <AccordianSummary/> is clicked.

    Login or Signup to reply.
  2. The issue in your code lies in how you are invoking the test function in the onClick event handler. Currently, you are invoking the test function immediately when rendering the component instead of passing it as a callback function.

    To fix this, you need to wrap the test function in an arrow function or a callback function to ensure it is called correctly when the onClick event occurs. Here’s the modified code:

    `const test = (e) => {
      console.log('example:', e.target.getAttribute('dataIWant'));
    }
    
    {records.map((item, index) => (
      <Accordion key={index}>
        <AccordionSummary
          onClick={(e) => test(e)}
          expandIcon={<ExpandMoreIcon />}
          aria-controls="panel1a-content"
          id="panel1a-header"
          dataIWant={item.attributes.id}
        >
          <Typography>{item.attributes.name} {item.attributes.date}</Typography>
        </AccordionSummary>
      </Accordion>
    ))}`
    

    In the modified code, the onClick event handler is wrapped in an arrow function (e) => test(e). This ensures that the test function is only called when the onClick event occurs, with the event object e passed as an argument.

    Additionally, the dataIWant attribute is added to the AccordionSummary component, and you can access it using e.target.getAttribute('dataIWant') in the test function.

    By making these changes, you should be able to access the specific piece of data (item.attributes.id) from the dataset when clicking on the accordion panel.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search