When developing in React there’s one error I commonly see in the console while debugging and it’s always this one:
Warning: Each child in a list should have a unique “key” prop.
<insert meme about harry, hermoine and ron>
Thankfully this is a very simple problem to fix, as the warning implies you just need to make sure that each iteration of the <li> tag has it’s own unique key assigned to it. Take, for example, this code:
import * as React from "react";
interface IProps {
Status: string;
}
interface IError {
Status: "400" | "401" | "402" | "403" | "404" | "500";
Description: string;
Color: string;
}
const ReactExample: React.FC<IProps> = React.memo(( props ) => {
const [errors, setErrors] = React.useState<IError[]>([]);
React.useEffect(() => {
if (props.Status == "400") {
newErrors.push({
Status: "400",
Description: "Bad request",
Color: "yellow"
});
}
if (props.Status == "401") {
newErrors.push({
Status: "401",
Description: "Unauthorized",
Color: "yellow"
});
}
if (props.Status == "402") {
newErrors.push({
Status: "402",
Description: "Payment Required",
Color: "yellow"
});
}
if (props.Status == "403") {
newErrors.push({
Status: "403",
Description: "Forbidden",
Color: "red"
});
}
if (props.Status == "404") {
newErrors.push({
Status: "404",
Description: "Not found",
Color: "yellow"
});
}
if (props.Status == "500") {
newErrors.push({
Status: "500",
Description: "Internal server error",
Color: "red"
});
}
setErrors(newErrors);
}, []);
return (
<div className="http-status-errors">
{errors.length > 0 ? (
<ul>
{errors.map((error: IError) => (
<li className={"color-" + error.Color}>
<span>{error.Description}</span>
</li>
))}
</ul>
) : null}
</div>
);
});
export default ReactExample;
To fix the error for this example you will want to not only add a key to the <li> tag but you will also need something you can pull a unique value from. Your absolute best bet will always be to use a GUID, and if working with an API you will ideally have one returned with the dataset. However in this example you’ll notice IError does not contain a GUID that we can use, however the Status property will be unique, so one solution might look like:
return (
<div className="http-status-errors">
{errors.length > 0 ? (
<ul>
{errors.map((error: IError) => (
<li key={error.Status} className={"color-" + error.Color}>
<span>{error.Description}</span>
</li>
))}
</ul>
) : null}
</div>
)
Unfortunately you aren’t always so lucky as to get a unique identity back with your data, so what do you do in that case? Well, as a last resort we can simply add an iterator to our map call and use that:
import * as React from "react";
interface IProps {
Status: string;
}
interface IError {
Status: "400" | "401" | "402" | "403" | "404" | "500";
Description: string;
Color: string;
}
const ReactExample: React.FC<IProps> = React.memo(( props ) => {
const [errors, setErrors] = React.useState<IError[]>([]);
React.useEffect(() => {
if (props.Status == "400") {
newErrors.push({
Status: "400",
Description: "Bad request",
Color: "yellow"
});
}
if (props.Status == "401") {
newErrors.push({
Status: "401",
Description: "Unauthorized",
Color: "yellow"
});
}
if (props.Status == "402") {
newErrors.push({
Status: "402",
Description: "Payment Required",
Color: "yellow"
});
}
if (props.Status == "403") {
newErrors.push({
Status: "403",
Description: "Forbidden",
Color: "red"
});
}
if (props.Status == "404") {
newErrors.push({
Status: "404",
Description: "Not found",
Color: "yellow"
});
}
if (props.Status == "500") {
newErrors.push({
Status: "500",
Description: "Internal server error",
Color: "red"
});
}
setErrors(newErrors);
}, []);
return (
<div className="http-status-errors">
{errors.length > 0 ? (
<ul>
{errors.map((error: IError, i) => (
<li key={i} className={"color-" + error.Color}>
<span>{error.Description}</span>
</li>
))}
</ul>
) : null}
</div>
);
});
export default ReactExample;
Save and reload your app and you’ll find that your warning is gone.
A seasoned Senior Solutions Architect with 20 years of experience in technology design and implementation. Renowned for innovative solutions and strategic insights, he excels in driving complex projects to success. Outside work, he is a passionate fisherman and fish keeper, specializing in planted tanks.