Skip to content
Advertisement

Creating unique key props for array children (React.js)

I am trying to build out a component in React which takes information from a JSON source, and uses some of that information to create states which can be passed down into other separate components. While I haven’t passed my states into separate components yet, I have been able to get my state to update with the information from the JSON. However, when I load my page I get an error code which I want to sort out before continuing with my project in case there are unintended side effects from leaving the error in my code. The error code reads as following:

index.js:1 Warning: Each child in a list should have a unique “key” prop.

Check the render method of FetchData

in div (at FetchData.js:27)

in FetchData (at App.js:8)

in div (at App.js:7)

My App.js looks like this:

import React from 'react';
import './App.css';
import FetchData from './Components/FetchData/FetchData';

function App() {
  return (
    <div className="App">
      <FetchData/>
    </div>
  );
}
export default App;

My FetchData.js looks like this:

import React from 'react';

class FetchData extends React.Component {
    constructor() {
        super();
        this.state = {
            portrait: null,
            title: null
        };
    }

    componentDidMount() {
        fetch('https://randomuser.me/api')
        .then (response => {
            return response.json();
        })
        .then (data => { 
            let userImage = data.results.map((person) => {
                return (
                    <div>
                        <img alt='portrait' img src={person.picture.large}/>
                    </div>
                )
            })
            let userTitle = data.results.map((person) => {                                  //line 27
                return (
                    <div key={person.results}>
                        <div> {person.name.title} </div>
                    </div>
                )
            })
            
            this.setState ({ 
                portrait: userImage,
                title: userTitle
             })
             console.log(this.portrait, this.title)
        })
    }
    
    render() {
        return (
            <div className='box1'>
                <div className='box2'>
                    <h2>{this.state.title}</h2>
                    {this.state.portrait}
                </div>
            </div>
        )
    }
};

export default FetchData;

and just in case since my index.js looks like this:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

serviceWorker.unregister();

I thought the issue was the fact that I used “person” into both my “data.results.map” so I tried to change the naming but that did not work either. Any help would be greatly appreciated!

Advertisement

Answer

The error is referring to your FetchData component.

The reconciliation algorithm in React can work if you assign an unique key to returned DOM objects. In this case, you are returning from the map function a list of similar DOM object. Any returned chunk have to declare the key attribute on the parent node.

In your case:

componentDidMount() {
        fetch('https://randomuser.me/api')
        .then (response => {
            return response.json();
        })
        .then (data => { 
            let userImage = data.results.map((person) => {
                return (
                    <div key={person.id}>
                        <img alt='portrait' img src={person.picture.large}/>
                    </div>
                )
            })
            let userTitle = data.results.map((person) => {                                  //line 27
                return (
                    <div key={person.id}>
                        <div> {person.name.title} </div>
                    </div>
                )
            })
            
            this.setState ({ 
                portrait: userImage,
                title: userTitle
             })
             console.log(this.portrait, this.title)
        })
    }

The key value must be an unique string and it is used by React to update the correct DOM nodes on state change. (I don’t know how your person.results is filled, but you need a sort of ID)

For simple component you can also use this syntax

            let userImage = data.results.map((person,idx) => {
                return (
                    <div key={idx}>
                        <img alt='portrait' img src={person.picture.large}/>
                    </div>
                )
            })

Be aware using this syntax, because idx is the position of the current element in the containing array, and if used more than one time, it results in duplicate keys (And React will think that nodes with same key are the same nodes)

User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement