7

I'm learning React and trying to figure out the best way to dynamically add props. I know two approaches how to do that, but cannot understand which one is better and faster.

First way is to use React.cloneElement api

const Parent = ({ children }) => {
  const child = React.cloneElement(children, { newProp: 'some new prop' });

  return child;
};

const Child = ({ newProp }) => <div>{newProp}</div>;

const App = () => (
  <Parent>
    <Child />
  </Parent>
);

The second way is to use "render props" pattern, described on official React site: Render Props

const Parent = ({ render }) => {
  const newProp = 'some new prop';

  return render(newProp);
}

const Child = ({ newProp }) => <div>{newProp}</div>;

const App = () => (
  <Parent render={props => <Child newProp={props} />} />
);

Both approaches give same results, but I don't know what is going on under the hood and which way to use.

3dGrabber
  • 4,710
  • 1
  • 34
  • 42
ValeryStatinov
  • 160
  • 1
  • 9

1 Answers1

4

React.cloneElement is a helper that's usually used to pass inline-props to avoid polluted codes. Instead of passing a prop down like this:

return <Child propA={myProps.propA} propB={myProps.propB} />

You can do this:

return React.cloneElement(Child, {...myProps})

Which is almost the same as:

 return <Child {...myProps} />

The only difference here is that cloneElement will preserve previously attached refs.

Now renderProps is a technique to reuse stateful logic and has different applications than cloneElement. The first will help you with props manipulation, the second is an equivalent to High Order Components and is used whenever you want to reuse some logic to dinamically inject props into your children:

class Animation extends Component{
   state = {} 
   componentDidMount(){/*...*/}
   componentDidUpdate(){/*...*/}

   render(){
       const { customProps } = this.state
       const { children } = this.props

       return children(customProps)
   }
}
Dupocas
  • 20,285
  • 6
  • 38
  • 56
  • 1
    Your example on `cloneElement` is misleading. It should reflect what the [documentation shows](https://reactjs.org/docs/react-api.html#cloneelement), mostly that you pass an `element` to `cloneElement` and that it's equivalent to using the ``. – Emile Bergeron Aug 02 '19 at 17:44
  • 1
    also, `React.cloneElement(Child, myProps)` is enough, no need to spread a new object unless you're going to add new props to it. – Emile Bergeron Aug 02 '19 at 17:45
  • I can also use `cloneElement` to _reuse stateful logic_. My `Parent` component in the example can have state like in your one and pass it to cloned child element as props. Isn't it right? – ValeryStatinov Aug 02 '19 at 18:16
  • Sure! It's just not as convenient but will work as well. – Dupocas Aug 02 '19 at 18:20
  • So there is no performance or memory difference, it is just like "style"? And `cloneElement` is not the preferred one. – ValeryStatinov Aug 02 '19 at 18:39
  • There is nothing wrong in use `cloneElement` to perform the prop injection, but the logic wrapped still needs to be inside an `HOC` or `renderProps` component. In terms of performance there is no difference between `cloneElement(Child, props)` and `` – Dupocas Aug 02 '19 at 18:43