render-prop helper to render anything (Functions, Components, Elements, ...)
npm install react-render-callback> render-prop helper to render anything (Functions, Components, Elements, ...)
[![version][version-badge]][package]
[![MIT License][license-badge]][license]
[![module formats: umd, cjs, and es][module-formats-badge]][unpkg-dist]
[![umd size][size-badge]][unpkg-dist]
[![umd gzip size][gzip-badge]][unpkg-dist]
[![Build Status][build-badge]][build]
[![Code Coverage][coverage-badge]][coverage]
[![Maintainability][maintainability-badge]][maintainability]
[![PRs Welcome][prs-badge]][prs]
[![Code of Conduct][coc-badge]][coc]
[![Sponsored by Kenoxa][sponsored-by-badge]][sponsored-by]
[![Semver][semver-badge]][semver]
[![semantic-release][semantic-release-badge]][semantic-release]
[![Greenkeeper badge][greenkeeper-badge]][greenkeeper]
You want your component to support the [render prop][render-prop] [pattern][use-a-render-prop]
with different types of values like
[Function as children][function-as-children],
a [React.Component][react-component] (Component Injection)
or just plain react elements.
react-render-callback frees you from detecting what kind fo [render prop][render-prop]
your component is dealing with:
``js
import React from 'react'
import renderCallback from 'react-render-callback'
class Component from React.Component {
state = {}
render() {
// can be any prop like render, component, renderHeader, ...
// children may be a function, a component, an element, ...
return renderCallback(this.props.children, this.state)
}
}
`
View an example in codesandbox.io.
- :package: Super tiny (~600 bytes)
- :ok_hand: Dependency free (except for Object.assign polyfill)
- :electric_plug: Just Works TM
- :crystal_ball: Tree shaking friendly (ESM, no side effects)
- :books: Well documented
- :100: test coverage
- :sunny: supports React v0.14, v15 and v16
- :family: supports rendering of
- Stateless Function Components (SFC)
with one argument (the common props case) aka _Render Props_ aka _Function as Child_false
or optional with several arguments
- Class Components aka _Component Injection_
- Context Provider and Consumer
- Forward Refs
- Factories
- Elements
with optional support for [cloning][clone-element] to merge props
- primitives like strings, numbers, arrays, ...
- , null, undefined and true are returned as null
just like in JSX
- Installation
- Usage
- API
- Examples
- Other Solutions
- Credits
- Contributors
- LICENSE
This module is distributed via [npm][npm] which is bundled with [node][node] and
should be installed as one of your project's dependencies:
`sh`
npm install --save react-render-callback
> This package also depends on react. Please make sure you
> have it installed as well.
The Universal Module Definition (UMD) is available
via unpkg.com and exposed as ReactRenderCallback.
`html`
#### renderCallback([ renderable [, props [, options ] ] ])
> renders the given renderable with props
`js`
// esm
import renderCallback from 'react-render-callback'
// commonjs
const renderCallback = require('react-render-callback')
renderable (optional): anything that can be rendered like a function, a component, or elements
- uses [React.createElement][create-element]defaultProps
for react types like
class components,
context provider or consumer,
forward refs,
factories, ...
- invokes stateless function components (SFC) respecting their
[][default-props]React.createElement
- not using [][create-element]propTypes
for improved performance
- except the SFC has andprocess.env.NODE_ENV
is not production, in that case React.createElement is used to
enable typechecking with [PropTypes][prop-types]
- gracefully handles other types like string, array,
[react elements][create-element], ...
props (optional): to pass to renderable
options (optional):
- cloneElement (default: false, since: v1.1.0): allows to pass props toReact.cloneElement
the element using [][clone-element]
`js
renderCallback(bar, {title: 'foo'})
// --> bar
renderCallback(bar, {title: 'foo'}, {cloneElement: true})
// --> bar
`
returns
- the created react element
- false, null, undefined and true are returned as null
just like in JSX
- the value as is for all other values
#### createRender([ renderable [, options ] ])
since: v1.1.0
> Returns a function ((...args) => ...) to render renderable with.
`js`
// esm
import {createRender} from 'react-render-callback'
// commonjs
const {createRender} = require('react-render-callback')
Accepts the same arguments (except props) as renderCallback(). It exists mainlyrenderable
to pre-determine (read cache) what type is, to prevent these
checks on every invocation.
Additionally the returned method accepts more than one argument (since: v1.2.0).
This allows to provide several parameters to the renderable.
`js`
const renderCallback = createRender((a, b, c) => ({a, b, c}))
renderCallback(1, 2, 3)
// -> { a: 1, b: 2, c: 3 }
> If the renderable has a defaultProps property only the first parameter is useddefaultProps
> and merged with the .
returns
a function ((...args) => ...) to render the args
A basic example showing the most common use cases can be viewed/edited at codesandbox.io.
#### Use options.cloneElement

> This option allows to pass down props without to need to create a function
> within render which merges the defined and provided props.
`js
class CountSeconds extends React.Component {
state = {
value: 0,
}
componentDidMount() {
this.timer = setInterval(() => {
this.setState(({value}) => ({value: value + 1}))
}, 1000)
}
componentWillUnmount() {
clearInterval(this.timer)
}
render() {
const {children, render = children} = this.props
return renderCallback(render, this.state, {cloneElement: true})
}
}
const DisplayValue = ({prefix = '', value}) => ${prefix}${value}
const App = ({prefix}) => (
)
`
#### Use createRender to pass down several arguments

`js
class CountSeconds extends React.Component {
state = {
value: 0,
}
reset = () => {
this.setState({value: 0})
}
componentDidMount() {
this.timer = setInterval(() => {
this.setState(({value}) => ({value: value + 1}))
}, 1000)
}
componentWillUnmount() {
clearInterval(this.timer)
}
render() {
const {children, render = children} = this.props
return createRender(render)(this.state.value, this.reset)
}
}
const DisplayValue = ({prefix = '', value}) => ${prefix}${value}
const App = () => (
{(value, reset) => (
)}
)
`
#### Use createRender to interop with a library which only supports functions as render-prop

`js
import Toggle from 'react-toggled'
class Toggler extends React.Component {
static defaultProps = {
onLabel: 'Toggled On',
offLabel: 'Toggled Off',
}
render() {
const {on, getTogglerProps, onLabel, offLabel} = this.props
return (
const ToggleView = createRender(Toggler)
const App = () =>
`
- render-props
- react-render-function
- @macklinu/render-props`
A special thanks needs to go to Kent C. Dodds for his great
video series (
egghead.io,
frontendmasters.com and
youtube.com).
His projects are either used in this project (kcd-scripts)
or are a template for the structure of this project (downshift).
Make sure to subscribe to his newsletter.
Thanks goes to these people ([emoji key][emojis]):
|
Sascha Tandel
💻 📖 🚇") ⚠️ 👀 📝 🐛 💡 🤔 📢 |
| :---: |
This project follows the [all-contributors][all-contributors] specification.
Contributions of any kind welcome!
MIT
[npm]: https://www.npmjs.com/
[node]: https://nodejs.org
[build-badge]: https://img.shields.io/travis/sastan/react-render-callback.svg?style=flat-square
[build]: https://travis-ci.org/sastan/react-render-callback
[coverage-badge]: https://img.shields.io/codecov/c/github/sastan/react-render-callback.svg?style=flat-square
[coverage]: https://codecov.io/github/sastan/react-render-callback
[version-badge]: https://img.shields.io/npm/v/react-render-callback.svg?style=flat-square
[package]: https://www.npmjs.com/package/react-render-callback
[npmcharts]: http://npmcharts.com/compare/react-render-callback
[license-badge]: https://img.shields.io/npm/l/react-render-callback.svg?style=flat-square
[license]: https://github.com/sastan/react-render-callback/blob/master/LICENSE
[prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square
[prs]: http://makeapullrequest.com
[coc-badge]: https://img.shields.io/badge/code%20of-conduct-ff69b4.svg?style=flat-square
[coc]: https://github.com/sastan/react-render-callback/blob/master/CODE_OF_CONDUCT.md
[gzip-badge]: http://img.badgesize.io/https://unpkg.com/react-render-callback/dist/react-render-callback.umd.min.js?compression=gzip&label=umd%20gzip%20size&style=flat-square
[size-badge]: http://img.badgesize.io/https://unpkg.com/react-render-callback/dist/react-render-callback.umd.min.js?label=umd%20size&style=flat-square
[unpkg-dist]: https://unpkg.com/react-render-callback/dist/
[module-formats-badge]: https://img.shields.io/badge/module%20formats-umd%2C%20cjs%2C%20es-green.svg?style=flat-square
[emojis]: https://github.com/kentcdodds/all-contributors#emoji-key
[maintainability]: https://codeclimate.com/github/sastan/react-render-callback/maintainability
[maintainability-badge]: https://api.codeclimate.com/v1/badges/bdb9f3ea6d70b6181b33/maintainability
[sponsored-by]: https://www.kenoxa.com
[sponsored-by-badge]: https://img.shields.io/badge/Sponsored%20by-Kenoxa-blue.svg
[all-contributors]: https://github.com/kentcdodds/all-contributors
[semantic-release]: https://github.com/semantic-release/semantic-release
[semantic-release-badge]: https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg
[greenkeeper]: https://greenkeeper.io/
[greenkeeper-badge]: https://badges.greenkeeper.io/sastan/react-render-callback.svg
[semver]: http://semver.org/spec/v2.0.0.html
[semver-badge]: https://img.shields.io/badge/SemVer-2.0.0-green.svg
[use-a-render-prop]: https://cdb.reacttraining.com/use-a-render-prop-50de598f11ce
[default-props]: https://reactjs.org/docs/react-component.html#defaultprops
[render-prop]: https://reactjs.org/docs/render-props.html
[function-as-children]: https://reactpatterns.com/#function-as-children
[react-component]: https://reactjs.org/docs/react-component.html
[create-element]: https://reactjs.org/docs/react-api.html#createelement
[clone-element]: https://reactjs.org/docs/react-api.html#cloneelement
[typechecking-with-proptypes]: https://reactjs.org/docs/typechecking-with-proptypes.html
[prop-types]: https://www.npmjs.com/package/prop-types