You'll notice that even though a warning is printed to the console, React still shows both Foo and Bar in your HTML being generated. React uses unique keys for reconciliations whilst trying to boost rendering performance. You can read more about this on the React reconciliation recursing on children page. Not providing keys means React cannot be as performant as it has been designed to be.
With regards to your question as to why a warning is not output to the console for nested arrays, we have to dive into the source code:
The function which generates the warning is called validateExplicitKey, and lives in the ReactElementValidator.js module.
This function is used in the validateChildKeys in the same module - looking into the source code gives the following, as of React 15.4.2:
function validateChildKeys(node, parentType) {
if (typeof node !== 'object') {
return;
}
if (Array.isArray(node)) { // 1.
for (var i = 0; i < node.length; i++) {
var child = node[i]; // 2.
if (ReactElement.isValidElement(child)) { // 3.
validateExplicitKey(child, parentType);
}
}
} else if (ReactElement.isValidElement(node)) {
// This element was passed in a valid location.
if (node._store) {
node._store.validated = true;
}
} else if (node) {
var iteratorFn = getIteratorFn(node);
// Entry iterators provide implicit keys.
if (iteratorFn) {
if (iteratorFn !== node.entries) {
var iterator = iteratorFn.call(node);
var step;
while (!(step = iterator.next()).done) {
if (ReactElement.isValidElement(step.value)) {
validateExplicitKey(step.value, parentType);
}
}
}
}
}
}
- An array of arrays will enter the first code block
- the
child will be set to child = ["b", Object] (where 'Object' is react's virtual dom representation for the br node we created via JSX)
the array will be run through the function ReactElement.isValidElement:
ReactElement.isValidElement = function (object) {
return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE;
};
with REACT_ELEMENT_TYPE being set as:
var REACT_ELEMENT_TYPE = typeof Symbol === 'function' && Symbol['for'] && Symbol['for']('react.element') || 0xeac7;
The array is an object, and is not null, but it's $$typeof property hasn't been set here, so the check fails.
$$typeof hasn't been set because React only adds this property to elements it creates to identify whether something is a React Element or not. This includes native HTML elements, and not data types.
Hence the ReactElement.isValidElement check fails, and the warning is never shown.
keyattribute to a native Array and offers the'react-addons-create-fragment'package in order to handle them.