Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why does the list render infinitely

I have two components – Contacts and ContactItem. In Contacts There is a div in which contacts are displayed and the "Add" button. In ContactItem there is a select with a choice of social network, textarea where you enter your number or nickname in the social network, the delete button. I need to implement the ability to remove and add new items

Now the problem is that I have an infinite number of renders when I click on the add button. How can it be fixed?
enter image description here

const Contacts = () => {
  const [contactItems, setContactItems] = useState([
    {
      index: 0,
      key: 0,
      id: 0,
    },
  ]);

  const addItemHandler = (event) => {
    event.preventDefault();
    const id = uuidv4();
    setContactItems(() => [
      ...contactItems,
      {
        index: contactItems.length,
        key: id,
        id,
      },
    ]);
  };

  const removeItemHandler = (id) => {
    setContactItems((contactItems) =>
      contactItems.filter((el) => el.id !== id)
    );
  };

  return (
    <>
      <div className={stylesCenter.channels}>
        {contactItems.map((item) => (
          <ContactItem
            index={item.index}
            key={item.key}
            id={item.id}
            removeItem={removeItemHandler}
          />
        ))}
      </div>
      <div>
        <button
          onClick={addItemHandler}
        >
          <img src="plus.svg" alt="plus logo" />
        </button>
      </div>
    </>
  );
};
const ContactItem = ({ index, removeItem }) => {
  console.log("child render", index);
  return (
    <div className={stylescenter.fullChannelControll}>
        <select className={stylescenter.selecterOptions} name="optionSelected">
          {options.map((el) => (
            <option key={el.value} value={el.value}>
              {el.label}
            </option>
          ))}
        </select>
      <div className={stylescenter.detailsAndInputAndDelete}>
        <textarea
          maxLength="100"
          rows="2"
        />
        <div className={stylescenter.removeButtons}>
          {index !== 0 && (
            <span>
              <IconButton onClick={removeItem(index)}>
                <img src="bin.svg" alt="bin logo" />
              </IconButton>
            </span>
          )}
        </div>
      </div>
    </div>
  );
};

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

You are actually passing the invocation of the function in the ContactItem component, inside the IconButton instead of the reference of the function that should be invoked onClick. Sounds tricky, but it’s logic!

This way you are calling the function for each render of the component. Since the function makes a setState you are getting the issue.

To avoid this, you can convert your click handler into an arrow function like this:

<IconButton onClick={() => removeItem(index)}>
    <img src="bin.svg" alt="bin logo" />
</IconButton>

This way you pass the reference of the arrow function for each render!

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading