From 69de4e171dad106e5256995900cdaa573d240e7c Mon Sep 17 00:00:00 2001 From: Sascha Tandel Date: Mon, 10 Sep 2018 09:33:03 +0200 Subject: [PATCH 1/3] doc(readme): add highlights section --- README.md | 80 ++++++++++++++++++++++++++++------------------------ package.json | 8 ++++-- 2 files changed, 48 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index 784fc51..3fbc94d 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,6 @@ # react-render-callback -> render anything (Function as Child, Render Props, Components, Elements, ...) - ---- +> render-prop helper to render anything (Functions, Components, Elements, ...) [![version][version-badge]][package] [![MIT License][license-badge]][license] @@ -24,47 +22,55 @@ ## The problem You want your component to support the [`render prop`][render-prop] [pattern][use-a-render-prop] -and you want to support several different types of values like +with different types of values like [Function as children][function-as-children], -a [React.Component][react-component] +a [React.Component][react-component] (Component Injection) or just plain react elements. ## This solution -`react-render-callback` frees you from detecting what kind of callback your component is dealing with: +`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' -import render from 'react-render-callback' - +// children may be a function, a component, an element, ... class Component from React.Component { state = {} render() { - // can be any prop: return render(this.props.renderHeader, this.state.header) - return render(this.props.children, this.state) + // can be any prop like render, component, renderHeader, ... + return renderCallback(this.props.children, this.state) } } ``` -It can render the following types: - -- [Stateless Function Components (SFC)](https://reactjs.org/docs/components-and-props.html#functional-and-class-components) - with one argument (the common `props` case) aka _Render Props Pattern_ - or [optional with several arguments](#use-createrender-to-pass-down-several-arguments) -- [Class Components](https://reactjs.org/docs/react-component.html) aka _Component Injection Pattern_ -- [Context](https://reactjs.org/docs/context.html) Provider and Consumer -- [Forward Refs](https://reactjs.org/docs/react-api.html#reactforwardref) -- [Factories](https://reactjs.org/docs/react-api.html#createfactory) -- [Elements](https://reactjs.org/docs/glossary.html#elements) - with [optional support](#use-optionscloneelement) for [cloning][clone-element] to merge props -- primitives like strings, numbers, arrays, ... -- `false`, `null`, `undefined` and `true` are returned as `null` - just like in [JSX](https://reactjs.org/docs/jsx-in-depth.html#booleans-null-and-undefined-are-ignored) - View an example in [codesandbox.io](https://codesandbox.io/s/48k5p1r764?module=%2FApp.js). +## Highlights + +- :package: Super tiny (~600 bytes) +- :ok_hand: Dependency free (except for [Object.assign](https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Object/assign) polyfill) +- :electric_plug: Plug and play +- :crystal_ball: Tree shaking friendly (ESM, no side effects) +- :books: Well documented +- :100: test coverage +- :family: supports rendering of + - [Stateless Function Components (SFC)](https://reactjs.org/docs/components-and-props.html#functional-and-class-components) + with one argument (the common `props` case) aka _Render Props_ aka _Function as Child_ + or [optional with several arguments](#use-createrender-to-pass-down-several-arguments) + - [Class Components](https://reactjs.org/docs/react-component.html) aka _Component Injection_ + - [Context](https://reactjs.org/docs/context.html) Provider and Consumer + - [Forward Refs](https://reactjs.org/docs/react-api.html#reactforwardref) + - [Factories](https://reactjs.org/docs/react-api.html#createfactory) + - [Elements](https://reactjs.org/docs/glossary.html#elements) + with [optional support](#use-optionscloneelement) for [cloning][clone-element] to merge props + - primitives like strings, numbers, arrays, ... + - `false`, `null`, `undefined` and `true` are returned as `null` + just like in [JSX](https://reactjs.org/docs/jsx-in-depth.html#booleans-null-and-undefined-are-ignored) + ## Table of Contents @@ -104,15 +110,15 @@ via [unpkg.com](https://unpkg.com/) and exposed as `ReactRenderCallback`. ### API -#### `render([ renderable [, props [, options ] ] ])` +#### `renderCallback([ renderable [, props [, options ] ] ])` > renders the given `renderable` with `props` ```js // esm -import render from 'react-render-callback' +import renderCallback from 'react-render-callback' // commonjs -const render = require('react-render-callback') +const renderCallback = require('react-render-callback') ``` **renderable** (optional): anything that can be rendered like a function, a component, or elements @@ -141,10 +147,10 @@ const render = require('react-render-callback') the element using [`React.cloneElement`][clone-element] ```js -render(bar, {title: 'foo'}) +renderCallback(bar, {title: 'foo'}) // --> bar -render(bar, {title: 'foo'}, {cloneElement: true}) +renderCallback(bar, {title: 'foo'}, {cloneElement: true}) // --> bar ``` @@ -167,21 +173,21 @@ import {createRender} from 'react-render-callback' const {createRender} = require('react-render-callback') ``` -Accepts the same arguments (except `props`) as `render()`. It exists mainly +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 render function. +This allows to provide several parameters to the `renderable`. ```js -const render = createRender((a, b, c) => ({a, b, c})) -render(1, 2, 3) +const renderCallback = createRender((a, b, c) => ({a, b, c})) +renderCallback(1, 2, 3) // -> { a: 1, b: 2, c: 3 } ``` -If only one argument is passed and it is a plain object, that argument is merged -with (if defined) the `defaultProps` of the `renderable`. +> If the `renderable` has a `defaultProps` property only the first parameter is used +> and merged with the `defaultProps`. **returns** @@ -301,7 +307,7 @@ const App = () => {ToggleView} ## Other Solutions -- [`render-props`](https://github.com/donavon/render-props) +- [`render-props`](https://www.npmjs.com/package/render-props) - [`react-render-function`](https://www.npmjs.com/package/react-render-function) - [`@macklinu/render-props`](https://www.npmjs.com/package/@macklinu/render-props) diff --git a/package.json b/package.json index 95b3dc3..d6d7c50 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "react-render-callback", "version": "0.0.0-semantically-released", - "description": "render anything (Function as Child, Render Props, Components, Elements, ...)", + "description": "render-prop helper to render anything (Functions, Components, Elements, ...)", "homepage": "https://github.com/sastan/react-render-callback#readme", "main": "dist/react-render-callback.cjs.js", "module": "dist/react-render-callback.esm.js", @@ -66,9 +66,11 @@ ], "keywords": [ "react", - "render-props", "render-prop", - "function-as-child" + "render-props", + "function-as-child", + "component-injection", + "facc" ], "publishConfig": { "access": "public" From e0d6c01bca0acc54ed107d37da83011bfe3ab38e Mon Sep 17 00:00:00 2001 From: Sascha Tandel Date: Mon, 10 Sep 2018 09:41:14 +0200 Subject: [PATCH 2/3] doc: adjust wording to be more clear of the intent --- README.md | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 3fbc94d..13b66ed 100644 --- a/README.md +++ b/README.md @@ -36,12 +36,12 @@ your component is dealing with: import React from 'react' import renderCallback from 'react-render-callback' -// children may be a function, a component, an element, ... 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) } } @@ -139,11 +139,11 @@ const renderCallback = require('react-render-callback') - gracefully handles other types like string, array, [react elements][create-element], ... -**props** (optional): to pass to `renderable` (if renderable is a function or react element type) +**props** (optional): to pass to `renderable` **options** (optional): -- `cloneElement` (default: `false`, since: v1.1.0): allows to pass props to +- `cloneElement` (default: `false`, since: v1.1.0): allows to pass `props` to the element using [`React.cloneElement`][clone-element] ```js @@ -156,6 +156,7 @@ renderCallback(bar, {title: 'foo'}, {cloneElement: true}) **returns** +- the created react element - `false`, `null`, `undefined` and `true` are returned as `null` just like in [JSX](https://reactjs.org/docs/jsx-in-depth.html#booleans-null-and-undefined-are-ignored) - the value as is for all other values @@ -191,7 +192,7 @@ renderCallback(1, 2, 3) **returns** -a function (`(...args) => ...`) +a function (`(...args) => ...`) to render the args ### Examples @@ -201,8 +202,8 @@ A basic example showing the most common use cases can be viewed/edited at [codes [![Edit](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/mj5py581oy) -> This option allows to pass down props without to need to create a function -> within render which merges the parent and received props. +> 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 { @@ -281,23 +282,29 @@ const App = () => ( ) ``` -#### Use `createRender` to interop with a library which only supports function as render-prop +#### Use `createRender` to interop with a library which only supports functions as render-prop [![Edit](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/1qyqwq14jq) ```js import Toggle from 'react-toggled' -const Toggler = ({on, getTogglerProps, onLabel, offLabel}) => ( -
- -
{on ? onLabel : offLabel}
-
-) +class Toggler extends React.Component { + static defaultProps = { + onLabel: 'Toggled On', + offLabel: 'Toggled Off', + } -Toggler.defaultProps = { - onLabel: 'Toggled On', - offLabel: 'Toggled Off', + render() { + const {on, getTogglerProps, onLabel, offLabel} = this.props + + return ( +
+ +
{on ? onLabel : offLabel}
+
+ ) + } } const ToggleView = createRender(Toggler) From b261fc110bfcafe61fd36fb49b12b220742d3793 Mon Sep 17 00:00:00 2001 From: Sascha Tandel Date: Mon, 10 Sep 2018 10:42:40 +0200 Subject: [PATCH 3/3] fix(release): manually release a patch version update doc/readme on npm --- other/manual-releases.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/other/manual-releases.md b/other/manual-releases.md index b68b3a2..154fc8a 100644 --- a/other/manual-releases.md +++ b/other/manual-releases.md @@ -41,4 +41,4 @@ change is to release a new patch version. Reference: # ``` -The number of times we've had to do a manual release is: 0 \ No newline at end of file +The number of times we've had to do a manual release is: 1