0

If you're mapping over an array to render elements and in the resulting array of elements you have a null and then 2 or more items with the same key, on each re-render, React will add another element to the DOM like those two.

Here's a minimal code for reproducing:

const LIST = [{ id: 2, done: true },{ id: 1 },{ id: 1 }];

function App() {
  const forceUpdate = React.useState()[1];
  return LIST.map(({ id, done }, i) => {
    if (done) {
      return null;
    }
    return (
      <p key={id} onMouseEnter={forceUpdate}>
        Index: {i}
      </p>
    );
  });
}

And here's that same code on CodeSandbox for playing with it: https://codesandbox.io/s/8kqxr

Notice that when you hover over the list (and therefore cause re-render), React adds an additional element to the resulting DOM.

The issue can be avoided by either of these:

  • ensuring unique id

  • moving all null elements to the end of the list

  • ensuring there are no null elements

I know React is NOT supporting elements with the same key and is warning that using those can result in errors, but I still wonder what exactly causes this? Can someone with an in-depth knowledge of JSX and React reconciliation explain it to me?

Leo Brdar
  • 3
  • 3
  • 2
    JavaScript's Array.map() function will return an array with the same number of items, regardless if any of the items are empty or null. – Bryan Elliott May 15 '19 at 20:00
  • sandbox link isnt working but you could add in `return LIST.map(same stuff you have).filter(item => item != null)` to remove the null elements. – Shawn Pacarar May 15 '19 at 20:05
  • 1
    @BryanElliott yes, I wasn't clear enough in my question. The array contains correct items, but the way React diffs virtual and actual DOM is broken and results in additional items being rendered. – Leo Brdar May 16 '19 at 11:03
  • @ShawnPacarar Yes, but JSX is supposed to ignore `null` element either way. For some reason, it seems it's not completely ignoring it. That's what I'm trying to find out here, it's more of a why is it happening kind of question, not how to fix it. – Leo Brdar May 16 '19 at 11:06

1 Answers1

1

I believe react uses keys to identify which components to update, since Index: 1 and Index: 2 both have the same key it gets confused on which to modify, hence it looks at the second (last occurrence of the key) in this case Index:2 and replaces it with the new re-rendered data

akshay kishore
  • 1,017
  • 8
  • 16