diff --git a/content/docs/render-props.md b/content/docs/render-props.md index 6991daac..f97295c3 100644 --- a/content/docs/render-props.md +++ b/content/docs/render-props.md @@ -222,3 +222,66 @@ function withMouse(Component) { ``` So using a render prop makes it possible to use either pattern. + +## Caveats + +### Be careful when using Render Props with React.PureComponent + +Using a render prop can negate the advantage that comes from using [`React.PureComponent`](https://reactjs.org/docs/react-api.html#reactpurecomponent) if you create the function inside a `render` method. This is because the shallow prop comparison will always return `false` for new props, and each `render` in this case will generate a new value for the render prop. + +For example, continuing with our `` component from above, if `Mouse` were to extend `React.PureComponent` instead of `React.Component`, our example would look like this: + +```js +class Mouse extends React.PureComponent { + // Same implementation as above... +} + +class MouseTracker extends React.Component { + render() { + return ( +
+

Move the mouse around!

+ + {/* + This is bad! The value of the `render` prop will + be different on each render. + */} + ( + + )}/> +
+ ); + } +} +``` + +In this example, each time `` renders, it generates a new function as the value of the `` prop, thus negating the effect of `` extending `React.PureComponent` in the first place! + +To get around this problem, you can sometimes define the prop as an instance method, like so: + +```js +class MouseTracker extends React.Component { + constructor(props) { + super(props); + + // This binding ensures that `this.renderTheCat` always refers + // to the *same* function when we use it in render. + this.renderTheCat = this.renderTheCat.bind(this); + } + + renderTheCat(mouse) { + return + } + + render() { + return ( +
+

Move the mouse around!

+ +
+ ); + } +} +``` + +In cases where you cannot bind the instance method ahead of time in the constructor (e.g. because you need to close over the component's props and/or state) you should extend `React.Component` instead.