mirror of
https://github.com/zebrajr/react.git
synced 2026-01-15 12:15:22 +00:00
Better warnings for missing keys on arrays
We have less dynamic arrays in the code base now so let's start warning for all the cases where we pass dynamic arrays without keys. I use the displayName to point out which component's render method was responsible. I only warn once per component. If the child was created in a different component (and passed as a property) I also show the owner of the child. Maybe it should've attached the key at a higher level. This does give false positives for arrays that are truly static. Those should probably be refactored to use the XML syntax if possible.
This commit is contained in:
committed by
Paul O’Shannessy
parent
37ddfa0521
commit
0e91febb9c
@@ -58,10 +58,12 @@ var ComponentLifeCycle = keyMirror({
|
||||
*/
|
||||
|
||||
var CHILD_HAS_NO_IDENTITY =
|
||||
'You are passing a dynamic array of children. You should set the ' +
|
||||
'property "key" to a string that uniquely identifies each child.';
|
||||
'Each child in an array should have a unique "key" prop. ' +
|
||||
'Check the render method of ';
|
||||
|
||||
var HAS_WARNED = false;
|
||||
var CHILD_CAME_FROM_ANOTHER_OWNER = '. It was passed a child from ';
|
||||
|
||||
var owner_has_warned = {};
|
||||
|
||||
/**
|
||||
* Helpers for flattening child arguments onto a new array or use an existing
|
||||
@@ -108,9 +110,28 @@ function assignKey(groupingIndex, child, index) {
|
||||
// This is in an array. This could grow and shrink or be reordered.
|
||||
// All children that doesn't already have autogenerated identity needs
|
||||
// to have an explicit key provided.
|
||||
if (!HAS_WARNED && key == null) {
|
||||
HAS_WARNED = true;
|
||||
console && console.warn && console.warn(CHILD_HAS_NO_IDENTITY);
|
||||
if (key == null) {
|
||||
// Name of the component whose render method tried to pass children.
|
||||
var currentName =
|
||||
ReactCurrentOwner.current &&
|
||||
ReactCurrentOwner.current.constructor.displayName;
|
||||
|
||||
// Name of the component that originally created this child.
|
||||
var childOwnerName =
|
||||
child.props[OWNER] && child.props[OWNER].constructor.displayName;
|
||||
|
||||
if (currentName && !owner_has_warned.hasOwnProperty(currentName)) {
|
||||
owner_has_warned[currentName] = true;
|
||||
var message = CHILD_HAS_NO_IDENTITY + currentName;
|
||||
if (childOwnerName && currentName !== childOwnerName) {
|
||||
// Usually the current owner is the offender, but if it accepts
|
||||
// children as a property, it may be the creator of the child that's
|
||||
// responsible for assigning it a key.
|
||||
message += CHILD_CAME_FROM_ANOTHER_OWNER + childOwnerName;
|
||||
}
|
||||
message += '.';
|
||||
console && console.warn && console.warn(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
child._key = createKey(key, index, groupingIndex);
|
||||
|
||||
Reference in New Issue
Block a user