maazadeeb
maazadeeb

Reputation: 6112

Does React handle keys automatically when using React.Children.map?

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:

  1. Does React.Children.map auto-generate keys for the elements we pass through it?
  2. 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

Upvotes: 22

Views: 8921

Answers (1)

Shubham Khatri
Shubham Khatri

Reputation: 281950

React.Children.map takes into account the key 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);
}

Upvotes: 18

Related Questions