Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When should I be using React.cloneElement vs this.props.children?

Tags:

reactjs

People also ask

What is props children and when you should use it?

Essentially, props. 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”.

What is React cloneElement and the difference with this props children?

The React. cloneElement() function returns a copy of a specified element. Additional props and children can be passed on in the function. You would use this function when a parent component wants to add or modify the prop(s) of its children.

Why would you use React children?

React. Children. map is a utility function to help you handle different cases. Invokes a function on every immediate child contained within children with this set to thisArg.

When should I use React cloneElement?

React. cloneElement() is useful when you want to add or modify the props of a parent component's children while avoiding unnecessary duplicate code.


props.children isn't the actual children; It is the descriptor of the children. So you don't have actually anything to change; you can't change any props, or edit any functionality; you can only read from it. If you need to make any modifications you have to create new elements using React.CloneElement.

https://egghead.io/lessons/react-use-react-cloneelement-to-extend-functionality-of-children-components

An example:

main render function of a component such as App.js:

render() {   
    return(
            <Paragraph>
              <Sentence>First</Sentence>
              <Sentence>Second</Sentence>
              <Sentence>Third</Sentence>
            </Paragraph>   
    ) 
}

now let's say you need to add an onClick to each child of Paragraph; so in your Paragraph.js you can do:

render() {
        return (
          <div>
          {React.Children.map(this.props.children, child => {
            return React.cloneElement(child, {
              onClick: this.props.onClick })   
         })}
         </div>
       ) 
}

then simply you can do this:

render() {   
  return(
        <Paragraph onClick={this.onClick}>
          <Sentence>First</Sentence>
          <Sentence>Second</Sentence>
          <Sentence>Third</Sentence>
        </Paragraph>   
   ) 
}

Note: the React.Children.map function will only see the top level elements, it does not see any of the things that those elements render; meaning that you are providing the direct props to children (here the <Sentence /> elements). If you need the props to be passed down further, let's say you will have a <div></div> inside one of the <Sentence /> elements that wants to use the onClick prop then in that case you can use the Context API to do it. Make the Paragraph the provider and the Sentence elements as consumer.


Edit:

Look at Vennesa's answer instead, which is a better explanation.

Original:

First of all, the React.cloneElement example only works if your child is a single React element.

For almost everything {this.props.children} is the one you want. Cloning is useful in some more advanced scenarios, where a parent sends in an element and the child component needs to change some props on that element or add things like ref for accessing the actual DOM element.

In the example above, the parent which gives the child does not know about the key requirement for the component, therefore it creates a copy of the element it is given and adds a key based on some unique identifier in the object. For more info on what key does: https://facebook.github.io/react/docs/multiple-components.html


In fact, React.cloneElement is not strictly associated with this.props.children.

It's useful whenever you need to clone react elements(PropTypes.element) to add/override props, without wanting the parent to have knowledge about those component internals(e.g, attaching event handlers or assigning key/ref attributes).

Also react elements are immutable.

React.cloneElement( element, [props], [...children] ) is almost equivalent to: <element.type {...element.props} {...props}>{children}</element.type>


However, the children prop in React is especially used for containment (aka composition), pairing with React.Children API and React.cloneElement, component that uses props.children can handle more logic(e.g., state transitions, events, DOM measurements etc) internally while yielding the rendering part to wherever it's used, React Router <switch/> or compound component <select/> are some great examples.

One last thing that worth mentioning is that react elements are not restricted to props.children.

function SplitPane(props) {
  return (
    <div className="SplitPane">
      <div className="SplitPane-left">
        {props.left}
      </div>
      <div className="SplitPane-right">
        {props.right}
      </div>
    </div>
  );
}

function App() {
  return (
    <SplitPane
      left={
        <Contacts />
      }
      right={
        <Chat />
      } />
  );
}

They can be whatever props that makes sense, the key was to define a good contract for the component, so that the consumers of it can be decoupled from the underlying implementation details, regardless whether it's using React.Children, React.cloneElement, or even React.createContext.