render-prop helper to render anything (Functions, Components, Elements, ...)
render-prop helper to render anything (Functions, Components, Elements, …)
You want your component to support the render prop
pattern
with different types of values like
Function as children,
a React.Component (Component Injection)
or just plain react elements.
react-render-callback
frees you from detecting what kind fo render prop
your component is dealing with:
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.
props
case) aka Render Props aka Function as Childfalse
, null
, undefined
and true
are returned as null
This module is distributed via npm which is bundled with node and
should be installed as one of your project’s dependencies
:
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
.
<script src="https://unpkg.com/react-render-callback/dist/react-render-callback.umd.min.js"></script>
renderCallback([ renderable [, props [, options ] ] ])
renders the given
renderable
withprops
// 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
React.createElement
defaultProps
React.createElement
propTypes
andprocess.env.NODE_ENV
is not production
, in that case React.createElement
is used toprops (optional): to pass to renderable
options (optional):
cloneElement
(default: false
, since: v1.1.0): allows to pass props
toReact.cloneElement
renderCallback(<a href="#bar">bar</a>, {title: 'foo'})
// --> <a href="#bar">bar</a>
renderCallback(<a href="#bar">bar</a>, {title: 'foo'}, {cloneElement: true})
// --> <a href="#bar" title="foo">bar</a>
returns
false
, null
, undefined
and true
are returned as null
createRender([ renderable [, options ] ])
since: v1.1.0
Returns a function (
(...args) => ...
) to renderrenderable
with.
// esm
import {createRender} from 'react-render-callback'
// commonjs
const {createRender} = require('react-render-callback')
Accepts the same arguments (except props
) as renderCallback()
. It exists mainly
to pre-determine (read cache) what type renderable
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
.
const renderCallback = createRender((a, b, c) => ({a, b, c}))
renderCallback(1, 2, 3)
// -> { a: 1, b: 2, c: 3 }
If the
renderable
has adefaultProps
property only the first parameter is used
and merged with thedefaultProps
.
returns
a function ((...args) => ...
) to render the args
A basic example showing the most common use cases can be viewed/edited at codesandbox.io.
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.
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}) => (
<CountSeconds>
<DisplayValue prefix={prefix} ></DisplayValue>
</CountSeconds>
)
createRender
to pass down several arguments
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 = () => (
<CountSeconds>
{(value, reset) => (
<React.Fragment>
<DisplayValue prefix="Seconds: " value={value} ></DisplayValue>
<button onClick={reset} type="button">
reset
</button>
</React.Fragment>
)}
</CountSeconds>
)
createRender
to interop with a library which only supports functions as render-prop
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 (
<div>
<button {...getTogglerProps()}>Toggle me</button>
<div>{on ? onLabel : offLabel}</div>
</div>
)
}
}
const ToggleView = createRender(Toggler)
const App = () => <Toggle>{ToggleView}</Toggle>
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):
Sascha Tandel 💻 📖 🚇 ⚠️ 👀 📝 🐛 💡 🤔 📢 |
---|
This project follows the all-contributors specification.
Contributions of any kind welcome!
MIT