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=".2.0/umd/react.development.js"></script>
<script src=".2.0/umd/react-dom.development.js"></script>
<div id="app">
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:
- Does
React.Children.map
auto-generate keys for the elements we pass through it? - If the answer to the above question is yes, then does it guarantee that the keys will remain unique and consistent across re-renders? By consistent I mean, re-ordered elements will produce the same keys when passed through it
1 Answer
Reset to default 18
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);
}
key
property is being set – ritesh Commented May 12, 2018 at 6:53React.Children.map
or not. The key will always be the index of the item in the array unless you've specified otherwise. Even when you get the warning, React has used the index. The difference is thatReact.Children.map
does not throw a warning about it. – Chris Commented May 12, 2018 at 9:37