I'm well aware of the reasons why one needs to add a key
prop when creating dynamic children in React. What's intriguing to me is the behavior of the below two pieces of code
This iterates over children
using just Array#map
const App = () => {
return (
<Parent>
<span>Child 1</span>
<span>Child 2</span>
<span>Child 3</span>
</Parent>
);
};
const Parent = ({ children }) => {
return children.map(child => (
<div style={{ background: "lightblue" }}>{child}</div>
));
};
ReactDOM.render(<App />, document.getElementById("app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.2.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.2.0/umd/react-dom.development.js"></script>
<div id="app">
This uses React.Children.map
to do the same
const App = () => {
return (
<Parent>
<span>Child 1</span>
<span>Child 2</span>
<span>Child 3</span>
</Parent>
);
};
const Parent = ({ children }) => {
return React.Children.map(children, child => (
<div style={{ background: "lightblue" }}>{child}</div>
));
};
ReactDOM.render(<App />, document.getElementById("app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.2.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.2.0/umd/react-dom.development.js"></script>
<div id="app">
The first snippet produces a warning
Each child in an array or iterator should have a unique "key" prop
whereas the second one doesn't produce any. So the two questions I have are:
React.Children.map
auto-generate keys for the elements we pass through it?children is a special prop, automatically passed to every component, that can be used to render the content included between the opening and closing tags when invoking a component. These kinds of components are identified by the official documentation as “boxes”.
A “key” is a special string attribute you need to include when creating lists of elements in React. Keys are used in React to identify which items in the list are changed, updated, or deleted. In other words, we can say that keys are used to give an identity to the elements in the lists.
Keys only make sense in the context of the surrounding array. For example, if you extract a ListItem component, you should keep the key on the <ListItem /> elements in the array rather than on the <li> element in the ListItem itself. A good rule of thumb is that elements inside the map() call need keys.
The Solution When creating a list in the UI from an array with JSX, you should add a key prop to each child and to any of its' children. React uses the key prop create a relationship between the component and the DOM element.
React.Children.map
takes into account thekey
that you have provided for the child components and adds a prefix to them, if the key is not provided to the children components, it adds a Implicit key determined by the index in the set while iterating to the mapped object
Below is a excerpt from the mapChildren
function form React src
function getComponentKey(component, index) {
// Do some typechecking here since we call this blindly. We want to ensure
// that we don't block potential future ES APIs.
if (
typeof component === 'object' &&
component !== null &&
component.key != null
) {
// Explicit key
return escape(component.key);
}
// Implicit key determined by the index in the set
return index.toString(36);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With