Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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
like image 794
maazadeeb Avatar asked May 12 '18 06:05

maazadeeb


People also ask

Is children a keyword in React?

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”.

How do React keys work?

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.

Where do you put the key in map React?

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.

How do you solve each child in a list should have a unique key prop?

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.


1 Answers

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);
}
like image 187
Shubham Khatri Avatar answered Oct 16 '22 16:10

Shubham Khatri