Add component stack info to key validation warnings (#6799)

* Add component stack info to key validation warnings

* Add `ReactComponentTreeDevtool.getStackAddendumByID`
This commit is contained in:
Keyan Zhang
2016-05-20 14:19:31 -07:00
parent 6a3e9d583b
commit 47e49ae8b7
11 changed files with 376 additions and 102 deletions
+22 -5
View File
@@ -11,6 +11,7 @@
'use strict';
var ReactComponentTreeDevtool = require('ReactComponentTreeDevtool');
var KeyEscapeUtils = require('KeyEscapeUtils');
var traverseAllChildren = require('traverseAllChildren');
var warning = require('warning');
@@ -19,8 +20,9 @@ var warning = require('warning');
* @param {function} traverseContext Context passed through traversal.
* @param {?ReactComponent} child React child component.
* @param {!string} name String name of key path to child.
* @param {number=} selfDebugID Optional debugID of the current internal instance.
*/
function flattenSingleChildIntoContext(traverseContext, child, name) {
function flattenSingleChildIntoContext(traverseContext, child, name, selfDebugID) {
// We found a component instance.
var result = traverseContext;
var keyUnique = (result[name] === undefined);
@@ -29,8 +31,9 @@ function flattenSingleChildIntoContext(traverseContext, child, name) {
keyUnique,
'flattenChildren(...): Encountered two children with the same key, ' +
'`%s`. Child keys must be unique; when two children share a key, only ' +
'the first child will be used.',
KeyEscapeUtils.unescape(name)
'the first child will be used.%s',
KeyEscapeUtils.unescape(name),
ReactComponentTreeDevtool.getStackAddendumByID(selfDebugID)
);
}
if (keyUnique && child != null) {
@@ -43,12 +46,26 @@ function flattenSingleChildIntoContext(traverseContext, child, name) {
* children will not be included in the resulting object.
* @return {!object} flattened children keyed by name.
*/
function flattenChildren(children) {
function flattenChildren(children, selfDebugID) {
if (children == null) {
return children;
}
var result = {};
traverseAllChildren(children, flattenSingleChildIntoContext, result);
if (__DEV__) {
traverseAllChildren(
children,
(traverseContext, child, name) => flattenSingleChildIntoContext(
traverseContext,
child,
name,
selfDebugID
),
result
);
} else {
traverseAllChildren(children, flattenSingleChildIntoContext, result);
}
return result;
}