@macklinu/render-props
A helper function to support various React render prop use cases
renderProps(props: Object, newProps: Object): ReactElement
Motivation
If you're building React components using render props, this library aims to simplify various render prop use cases.Installation
npm install @macklinu/render-props
Example
See this CodeSandbox for an in-browser example.See
src/types/example.tsx
for a TypeScript example and using the provided TypeScript types.Usage
Let's build aCounter
component using a traditional render prop.import React from 'react'
class Counter extends React.Component {
state = { count: 0 }
render() {
return this.props.render({
count: this.state.count,
increment: this.increment,
decrement: this.decrement,
})
}
increment = () => {
this.setState(prevState => ({ count: prevState.count + 1 }))
}
decrement = () => {
this.setState(prevState => ({ count: prevState.count - 1 }))
}
}
This works well if you only support a
render
prop function:<Counter
render={props => (
<div>
<span>{props.count}</span>
<button onClick={props.decrement}>-</button>
<button onClick={props.increment}>+</button>
</div>
)}
/>
But what if you want to use a prop other than
render
? For example, a children
function prop is popular alternative to render
:<Counter>
{props => (
<div>
<span>{props.count}</span>
<button onClick={props.decrement}>-</button>
<button onClick={props.increment}>+</button>
</div>
)}
</Counter>
This is where
@macklinu/render-props
comes into play. It allows render props named component
, render
, and children
(in that order), making it simpler for your React components to support common render prop APIs.import React from 'react'
import renderProps from '@macklinu/render-props'
class Counter extends React.Component {
state = { count: 0 }
render() {
return renderProps(this.props, {
count: this.state.count,
increment: this.increment,
decrement: this.decrement,
})
}
increment = () => {
this.setState(prevState => ({ count: prevState.count + 1 }))
}
decrement = () => {
this.setState(prevState => ({ count: prevState.count - 1 }))
}
}
And now you can use all cases:
<div>
<Counter
component={props => (
<div>
<h2>
Using the <code>component</code> prop
</h2>
<span>{props.count}</span>
<button onClick={props.decrement}>-</button>
<button onClick={props.increment}>+</button>
</div>
)}
/>
<Counter
render={props => (
<div>
<h2>
Using the <code>render</code> prop
</h2>
<span>{props.count}</span>
<button onClick={props.decrement}>-</button>
<button onClick={props.increment}>+</button>
</div>
)}
/>
<Counter>
{props => (
<div>
<h2>
Using the <code>children</code> prop
</h2>
<span>{props.count}</span>
<button onClick={props.decrement}>-</button>
<button onClick={props.increment}>+</button>
</div>
)}
</Counter>
</div>
API Reference
renderProps(props: Object, newProps: Object): ReactElement
props
: Theprops
object from a React componentnewProps
: The props object passed into the render prop function (component
,render
, orchildren
), which can be used by consumer components for rendering a React element.
Returns the React element returned from the
component
, render
, or children
prop. If none of those props are provided, returns null
.Contributors
Thanks goes to these wonderful people (emoji key):|
Macklin Underdown
💻 📖 ⚠️ | | :---: |
This project follows the all-contributors specification. Contributions of any kind welcome!