3

I have the following iteration of option elements for a select list:

{allCustomers.map(customer => { console.log(customer.id); console.log(typeof(customer.id)); return ( <option key={customer.id} > {customer.name} </option> ); })} 

The list of customers I have all have unique ids and the id property is of type number. Here is what I see in the console for the logs statements I have:

1 number 2 number 3 number 4 

With the snippet above I kept getting:

Warning: Each child in a list should have a unique "key" prop.

Then I tried the following and React was happy:

key={'' + customer.id} 

Is this the proper way to use numbers as key in React? What is the reason that React is thinking I have duplicate keys in case I leave them as numbers?

Edit This is the allCustomers list I have:

[ {id: 1, name: "Test Customer - 1", orderSchedules: Array(1)} {id: 2, name: "Test Customer - 2", orderSchedules: Array(0)} {id: 3, name: "Another Test Customer", orderSchedules: Array(1)} {id: 4, name: "Foo Bar Baz", orderSchedules: Array(1)} ] 

Edit - Full Code

import React from "react"; export default (props) => { const { orderSchedule, setOrderSchedule, allCustomers, saveHandler, } = props; return ( <> <h3>Order Schedule Details</h3> <hr/> <form onSubmit={saveHandler}> <div className="form-group row"> <label htmlFor="order-schedule-detail-description-input">Order Schedule Description</label> <input id="order-schedule-detail-description-input" type="text" className="form-control" value={orderSchedule.description} onChange={(event) => { setOrderSchedule({ ...orderSchedule, description: event.target.value }) }}/> <br/> <br/> <select className="custom-select" onChange={event => { setOrderSchedule({ ...orderSchedule, customer: { id: event.target.value } }); }} > {allCustomers && allCustomers.map(customer => { return ( <option value={customer.id} key={customer.id} > {customer.name} </option> ); })} </select> </div> <div className="form-group row"> <button type="submit" className="btn btn-primary" > Save </button> &nbsp; </div> </form> </> ); } 

Edit - My Container Class

import React, {useEffect, useState} from "react"; import {useParams} from "react-router-dom"; import * as orderScheduleController from "./orderScheduleController"; import * as customerController from "./../customer/customerController"; import OrderScheduleDetails from "./OrderScheduleDetails"; export default ({history}) => { let {id} = useParams(); const [orderSchedule, setOrderSchedule] = useState({ description: '', customer: {} }); const [allCustomers, setAllCustomers] = useState([{}]); useEffect(() => { if (id) { orderScheduleController.getOrderSchedule(id) .then(response => { setOrderSchedule(response.data); }); } }, []); useEffect(() => { customerController.getAllCustomers() .then(response => { setAllCustomers(response.data); }); }, []); function saveHandler(event) { event.preventDefault(); if (!orderSchedule.description) { return; } orderScheduleController .createOrderSchedule(orderSchedule) .then(() => { history.push('/orderSchedules'); }); } return ( <OrderScheduleDetails orderSchedule={orderSchedule} setOrderSchedule={setOrderSchedule} allCustomers={allCustomers} saveHandler={saveHandler} /> ) } 
7
  • Does this answer your question? ReactJS : What is the best way to give keys in array element This article may also be helpful. Commented Feb 29, 2020 at 17:55
  • @jmargolisvt No, that does not answer my question. Commented Feb 29, 2020 at 17:59
  • @jmargolisvt The article you linked is not related to my question either. Commented Feb 29, 2020 at 18:00
  • I think they answer "what is the proper way to use numbers as key in React?" They also explain why it's complaining. Do you specifically want to know why concatenating the space fools React here? Commented Feb 29, 2020 at 18:02
  • 1
    @JaredSmith I am using "react": "^16.12.0", and "react-dom": "^16.12.0", and "react-router": "^5.1.2", and "react-scripts": "^3.3.0", and "react-transition-group": "^2.5.1". Commented Feb 29, 2020 at 19:12

1 Answer 1

3

Keys have to be unique across their siblings. It's possible that you have other children that are being rendered inside of the parent container that share one or more of the keys you’re specifying here. Your '' + customer.id hack would work because 1 === '1' is false.

Sign up to request clarification or add additional context in comments.

7 Comments

You are most likely right. When I try customer.id + 10 everything is also fine again. But I can't find anything that may be clashing.. I posted the full component, could you take a look.. What are siblings? Where would I have a clash here, this is a form with one text input and one select list..
@KorayTugay Just had a look at your code; any chance that setOrderSchedule adds a customer to the allCustomers array? Your onChange callback is setting an id property on an object assigned to a customer property to e.target.value, but your <option> elements have no value and thus e.target.value is likely undefined.
Sorry, it was bad copy/paste, I do have value. setOrderSchedule does not modify the array. I will paste the container I have too, but nevermind please, this is getting out of control and I do not want to steal your time. However, it is very strange since I do not have any loops or any keys anywhere else..
@KorayTugay Just had a look; we’re all hung up on the “unique” bit, but the issue is your initial value to useState includes an empty object, i.e. one with an id of undefined, which prompts React to warn about a missing key.
Nah, it is not related.. Even if I start with -1 there, I still have the same problem. And I said, if I add customer.id + 10 all seems fine. Thank you for your support, I really do not want to steal your time on this one. I will accept your answer, I am unable to find myself what the problem is..
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.