Lars Nyström
Lars Nyström

Reputation: 6373

Do I need to specify the key prop in this case and how would I do that then?

The following code seems to work as expected: (fiddle)

const headers = [
    {
        id: 'section-1',
        header: 'section 1',
    },
    {
        id: 'section-2',
        header: 'section 2',
    },
    {
        id: 'section-3',
        header: 'section 3',
        children: [
            {
                id: 'section-31',
                header: 'section 31',
                children: [
                    {
                        id: 'section-311',
                        header: 'section 311',
                    },
                    {
                        id: 'section-312',
                        header: 'section 312',
                    },
                ],
            },
            {
                id: 'section-32',
                header: 'section 32',
            },
        ],
    },
    {
        id: 'section-4',
        header: 'section 4',
    },
];

const Nav = ({ headers, className }) =>
    <ul className={className}>
        {headers.map((header) => [
            <li className="list-group-item">
                {header.header}
            </li>,
            (header.children && header.children.length) ? (
                <Nav className="list-group" headers={header.children} />
            ) : null,
        ])}
    </ul>

const Toc = () =>
    <div id="my-super-interesting-nav">
        <Nav className="list-group nav-root" headers={headers} />
    </div>

I the future the headers array will be dynamic. I have three questions:

Why doesn't React complain that I haven't set the key prop on the child of the headers.map() call in Nav?

How bad will this confuse the reconciliation algorithm, given that the second assumption in the React reconciliation algorithm no longer holds?

If I wanted to specify a key in this case, how would I do that?

Upvotes: 1

Views: 658

Answers (2)

mitchken
mitchken

Reputation: 800

Since you are mapping an object in ReactJS, you will always have to add a key to it.

From the moment a loop or any other form of iteration is used this is required.

Just adding a key with the same value as id will fix it:

key={id}

Let me know if you need more information.

headers.map((header, index) => {
   <div key={index}>
      header
   </div>
}

Upvotes: 0

Konstantin Vitkovsky
Konstantin Vitkovsky

Reputation: 1228

The mapping function you use returns an array of elements, and not a react element, so key property is not expected thus no warning are being given.

I would advise you to refactor your code for mapping function to return react element like so:

{headers.map((header) =>
    <li className="list-group-item" key={header.id}>
        {header.header}
        {
            (header.children && header.children.length) 
            ? <Nav className="list-group" headers={header.children} /> 
            : null
        }
    </li>
)}

Note, that now we are able to use the key property and it's benefits.

https://jsfiddle.net/opm3Lsg8/2/

Upvotes: 1

Related Questions