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 render-propper
RenderPropper aims to create functional render props. The example below helps break down how RenderPropper accomplishes this goal:
import { renderProp } from 'render-propper';
/*
* Determines how to transform the input into a result that can be used by the renderer.
* The current logic is an identity function that returns what it receives.
*
* Assuming the string 'value' as input: 'value' would be returned to the renderer.
*/
const logic = input => input;
/*
* Determines how to render the results to output.
* The current logic is again an identity function, it returns what it receives.
*
* NOTE: Typically the renderer would return object or html that renders to the DOM,
* however anything can be rendered as the output.
*
* Again assuming the string 'value' as the result: 'value' would be returned (rendered) as output.
*/
const renderer = results => results;
/*
* Generates the actual render prop using the renderer and logic.
*
* Returns a function awaiting the input.
*/
const PassThrough = renderProp(() => renderer, logic);
// Any value passed in will go through both logic and renderer and be returned.
PassThrough(value); // 'value'
PassThrough(5); // 5
PassThrough(false); // false
The basic examples below take an object in and pass the same object back.
All examples below use the same functional logic:
import * as R from 'ramda';
import { renderProp } from 'render-propper';
const PassThrough = renderProp(R.prop('children'), R.prop('value'));
The PassThrough example using React.
import * as React from 'react';
const component = (
<PassThrough value="value">{result => <div>{result}</div>}</PassThrough>
);
// <div>value</div>
The PassThrough example using an object.
const object = {
children: results => {
const div = document.createElement('div');
div.innerHTML = results;
return div;
},
value: 'value'
};
PassThrough(object);
// <div>value</div>
All examples below utilize the same functional logic:
import * as R from 'ramda';
import { renderProp } from 'render-propper';
const isEven = n => n % 2 === 0;
const sumEvenNumbers = R.compose(
R.sum,
R.filter(isEven),
R.prop('array')
);
const SumEven = renderProp(R.prop('children'), sumEvenNumbers);
import * as React from 'react';
const component = (
<SumEven array={[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]}>
{result => <div>{result}</div>}
</SumEven>
);
// <div>30</div>
const example = {
children: results => {
const div = document.createElement('div');
div.innerHTML = results;
return div;
},
array: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
};
PassThrough(object);
// <div>30</div>
All exports have the following Typescript generics associated with them:
renderProps<Input, Results, Output>(...)
/**
* These default to any if not set:
*
* Input - The value coming in to the RenderProp
* Results - The value passed from the logic function to the renderer function
* Output - The output of the renderer function
*/
renderProps(renderer: Function);
renderProps(renderer: Function, logic: Function);
renderProp is curried which makes it useful to create render prop and render prop generator functions:
- Passing both parameters, renderer and logic functions, creates a render prop function
- Passing one parameters, renderer function, creates a render prop generator function that can generate any of render prop functions with different logic.
(childrenRenderProps is an example of a render prop generator function).
// Non-functional example for demonstration purposes:
const exampleRenderProp = renderProp(R.prop('example'));
const LastNameList = exampleRenderProp(... lastNameFunction ...);
const FullNameList = exampleRenderProp(... fullNameFunction ...);
const nameMap = (name, index) => <div key={index}>{name}</div>);
<LastNameList names={... namesArray ...} example={names => names.map(nameMap)} />
<FullNameList names={... namesArray ...} example={names => names.map(nameMap)} />
childrenRenderProp(logic: Function);
In React, the children prop (explicitly or implicitly) is often used for render props. This function makes creating a children render prop a bit easier.
// Non-functional example for demonstration purposes:
const LastNameList = childrenRenderProp(... lastNameFunction ...);
const FullNameList = childrenRenderProp(... fullNameFunction ...);
const nameMap = (name, index) => <div key={index}>{name}</div>);
<LastNameList names={... namesArray ...} children={names => names.map(nameMap)} /> // Explicit
<FullNameList names={... namesArray ...}>{names => names.map(nameMap)}</FullNameList> // Implicit
The main inspiration came from having fun connecting the Ramda library with React.
I'm not aware of any, if you are please make a pull request and add it here!
Thanks goes to these people (emoji key):
smacpherson64 π» π¨ π π€ |
Chad Watson π¬ π» π¨ π€ |
---|
This project follows the all-contributors specification. Contributions of any kind welcome!
MIT