Home > Back-end >  Always get the id of the last iteration ReactJS
Always get the id of the last iteration ReactJS

Time:07-10

I'm trying to select an id using a onClick method, the only problem is that when i click a button only the last id is displayed.

const renderTableData = () => {
let id = 0;
return (
  <tr>
    {days.map((val) => (
      <td>
        {timeSlot.map((time, i) => {
          if (occupiedSlots().result.includes(id   1)) {
            return (
              <button id={id  } className="disabledButton">
                {time}
              </button>
            );
          } else {
            return (
              <button id={id  } className="activeButton" onClick ={() => {canBookSlot({id})}}> 
                {time}
              </button>
            );
          }
        })}
      </td>
    ))}
  </tr>
);
};

This is what the canBookSlot() function looks like:

 const canBookSlot = (id) => {
let userDetailsString = localStorage.getItem("userDetails");
const userDetailsObj = JSON.parse(userDetailsString)

if(userDetailsObj.canBook != 0){
      Axios.post('http://localhost:3001/api/book/week1/ex', {
         room: userDetailsObj.room,
         id: id
    })

    return console.log(id) 
} else {
  return console.log("somethings wrong")
}

};

The output is always 70. how do i fix this?

CodePudding user response:

Consider your variable called days - if something else did days = null; you would expect your days.map to fail when it next renders. id is no different - every button is using the same id variable, so when you increase it, all usage of that value will witness that increase too.

So, you need to "capture" the current value of id for a given button. Due to the way how scope works in JS, a function body has its own set of variables. Because you are inside the function callback of map, that means we can define a buttonId variable inside it, and it will naturally be per button:

const renderTableData = () => {
let id = 0;
return (
  <tr>
    {days.map((val) => (
      <td>
        {timeSlot.map((time, i) => {
          var buttonId = id  ;
          if (occupiedSlots().result.includes(buttonId   1)) {
            return (
              <button id={buttonId} className="disabledButton">
                {time}
              </button>
            );
          } else {
            return (
              <button id={buttonId} className="activeButton" onClick ={() => {canBookSlot({id: buttonId})}}> 
                {time}
              </button>
            );
          }
        })}
      </td>
    ))}
  </tr>
);
};

CodePudding user response:

id is a global variable, and react itself has no idea of, everytime your table renders a button:

<button id={id  }> </button>

The value of id increases by id . And after the whole table gets rendered, the final value of id got incremented to the total length of the whole 2d array - 70. (I'm pretty sure you've disabled strickMode, otherwise the value could've doubled.)

So, that's the reason why you'll always get the last id. There're several ways to solve this, but the key is to understand why react use key prop for rendering array in the first place, for more detailed explanation, you can look up this answer.

  • Related