@macklinu/render-props

A helper function to support various React render prop use cases

Downloads in past

Stats

StarsIssuesVersionUpdatedCreatedSize
@macklinu/render-props
321.0.16 years ago6 years agoMinified + gzip package size for @macklinu/render-props in KB

Readme

@macklinu/render-props
A helper function to support various React render prop use cases

npm Build Status license code style: prettier semantic-release All Contributors



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 a Counter 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: The props object from a React component
  • newProps: The props object passed into the render prop function (component, render, or children), 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!