34

Application works, my classes really adds a new element but I see below warning in console!

Warning: Encountered two children with the same key, [object Object]. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — the behavior is unsupported and could change in a future version. in div (created by ContentBody) in ContentBody

Here is my render part :

 return (
            <div ref={this.myRef} style={this.state.myHomeStyle} >
              {this.state.elements.map((i: any) => {
                console.log(">>i>>>>", i);
                return <span style={i.myStyle} key={i} >{i}</span>;
              })}
            </div>
        );

// Where i init 
 public componentDidMount() {

    console.log('componentDidMount');
    this.myDOM  = this.myRef.current;
    this.myDOM.addEventListener(myEventsList.adaptCss, this.adaptCss);

    this.add(12,this.INLINE_TEST_ELE, null);
    this.add(13,this.INLINE_TEST_ELE, null);

  }


// Function add 
private add = (id: number, content: any, event: any ) => {

    let localArr: any[] = [];
    let mEvent: any = null;

    if (event !== undefined) {
      mEvent = event;
    }

    localArr = this.state.elements;
    localArr.push(React.createElement("div", { key: id , onClick : mEvent }, content));

    this.setState(
      {
        elements: localArr,
        visibility : true,
      },
    );

  }

Any suggestions?

Update: Here is the link for my starter project: https://github.com/zlatnaspirala/react-vs-typescript-starter

Nikola Lukic
  • 4,001
  • 6
  • 44
  • 75

3 Answers3

41

You can pass another parameter within your map function like so:

this.state.elements.map((element, index) => {
   return <span style={element.myStyle} key={index} >{element}</span>;
});

The second parameter of the Array.prototype.map function actually contains the current index of the particular element in that array.

This way, you'll be sure that your key is not duplicated.

heyitsmarcucu
  • 612
  • 5
  • 9
  • 49
    We are not encouraged to use index as key – Hemadri Dasari Sep 07 '18 at 09:57
  • Then maybe use the element's id as the key or any other properties of the object that is unique. I need to also know the contents of the `this.state.elements` please state it on your question so we are all aware. – heyitsmarcucu Sep 07 '18 at 09:58
  • 7
    Warning! Using the index in a map may work but is not a good idea. When you swap out items in a list, the key will stay the same and that will *fool* React into thinking it doesn't need to update. See this blog post for a full explanation https://medium.com/@robinpokorny/index-as-a-key-is-an-anti-pattern-e0349aece318 – Joe Seifi Jul 27 '20 at 04:45
  • 1
    From https://reactjs.org/docs/lists-and-keys.html#keys: "When you don’t have stable IDs for rendered items, you may use the item index as a key as a last resort. [...] We don’t recommend using indexes for keys if the order of items may change. This can negatively impact performance and may cause issues with component state. [...] If you choose not to assign an explicit key to list items then React will default to using indexes as keys." Also see https://robinpokorny.medium.com/index-as-a-key-is-an-anti-pattern-e0349aece318 – Shawn Oct 22 '21 at 17:51
5

You are passing element not index. And if your element is same then the error is being thrown. To pass the index use second param:

.map((element, index)=>

Now, using index will give you different key.

Bhojendra Rauniyar
  • 83,432
  • 35
  • 168
  • 231
  • 5
    Using index is not a good choice. – Ashish Duklan Nov 19 '20 at 11:38
  • 3
    From https://reactjs.org/docs/lists-and-keys.html#keys: "When you don’t have stable IDs for rendered items, you may use the item index as a key as a last resort. [...] We don’t recommend using indexes for keys if the order of items may change. This can negatively impact performance and may cause issues with component state. [...] If you choose not to assign an explicit key to list items then React will default to using indexes as keys." Also see https://robinpokorny.medium.com/index-as-a-key-is-an-anti-pattern-e0349aece318 – Shawn Oct 22 '21 at 17:51
3

See this for more understanding in "key" related warnings and best practices

 function ListItem(props) {
  // Correct! There is no need to specify the key here:
  return <li>{props.value}</li>;
}

function NumberList(props) {
  const numbers = props.numbers;
  const listItems = numbers.map((number) =>
    // Correct! Key should be specified inside the array.
    <ListItem key={number.toString()}
              value={number} />

  );
  return (
    <ul>
      {listItems}
    </ul>
  );
}

const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
  <NumberList numbers={numbers} />,
  document.getElementById('root')
);

Visit this link https://reactjs.org/docs/lists-and-keys.html#extracting-components-with-keys for more information