• Stars
    star
    611
  • Rank 73,401 (Top 2 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created almost 7 years ago
  • Updated over 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Compose render prop components

React Composer

Travis build status npm version npm downloads Test Coverage gzip size

Compose render prop components.

Motivation

Render props are great. Using a component with a render prop looks like the following:

<RenderPropComponent {...config}>
  {result => <MyComponent result={result} />}
</RenderPropComponent>

Sometimes you need the result of multiple render prop components inside of MyComponent. This can get messy.

<RenderPropComponent {...config}>
  {resultOne => (
    <RenderPropComponent {...configTwo}>
      {resultTwo => (
        <RenderPropComponent {...configThree}>
          {resultThree => (
            <MyComponent results={{ resultOne, resultTwo, resultThree }} />
          )}
        </RenderPropComponent>
      )}
    </RenderPropComponent>
  )}
</RenderPropComponent>

Nesting render prop components leads to rightward drift of your code. Use React Composer to prevent that drift.

import Composer from 'react-composer';

<Composer
  components={[
    <RenderPropComponent {...configOne} />,
    <RenderPropComponent {...configTwo} />,
    <RenderPropComponent {...configThree} />
  ]}>
  {([resultOne, resultTwo, resultThree]) => (
    <MyComponent results={{ resultOne, resultTwo, resultThree }} />
  )}
</Composer>;

Installation

Install using npm:

npm install react-composer

or yarn:

yarn add react-composer

API

This library has one, default export: Composer.

<Composer />

Compose multiple render prop components together. The props are as follows:

props.children

A render function that is called with an array of results accumulated from the render prop components.

<Composer components={[]}>
  {results => {
    /* Do something with results... Return a valid React element. */
  }}
</Composer>

props.components

The render prop components to compose. This is an array of React elements and/or render functions that are invoked with a render function and the currently accumulated results.

<Composer
  components={[
    // React elements may be passed for basic use cases
    // props.children will be provided via React.cloneElement
    <Outer />,

    // Render functions may be passed for added flexibility and control
    ({ results, render }) => (
      <Middle previousResults={results} children={render} />
    )
  ]}>
  {([outerResult, middleResult]) => {
    /* Do something with results... Return a valid React element. */
  }}
</Composer>

Note: You do not need to provide props.children to the React element entries in props.components. If you do provide props.children to these elements, it will be ignored and overwritten.

props.components as render functions

A render function may be passed instead of a React element for added flexibility.

Render functions provided must return a valid React element. Render functions will be invoked with an object containing 2 properties:

  1. results: The currently accumulated results. You can use this for render prop components which depend on the results of other render prop components.
  2. render: The render function for the component to invoke with the value produced. Plug this into your render prop component. This will typically be plugged in as props.children or props.render.
<Composer
  components={[
    // props.components may contain both elements and render functions
    <Outer />,
    ({ /* results, */ render }) => <SomeComponent children={render} />
  ]}>
  {results => {
    /* Do something with results... */
  }}
</Composer>

Examples and Guides

Example: Render prop component(s) depending on the result of other render prop component(s)

<Composer
  components={[
    <Outer />,
    ({ results: [outerResult], render }) => (
      <Middle fromOuter={outerResult} children={render} />
    ),
    ({ results, render }) => (
      <Inner fromOuterAndMiddle={results} children={render} />
    )
    // ...
  ]}>
  {([outerResult, middleResult, innerResult]) => {
    /* Do something with results... */
  }}
</Composer>

Example: Render props named other than props.children.

By default, <Composer /> will enhance your React elements with props.children.

Render prop components typically use props.children or props.render as their render prop. Some even accept both. For cases when your render prop component's render prop is not props.children you can plug render in directly yourself. Example:

<Composer
  components={[
    // Support varying named render props
    <RenderAsChildren />,
    ({ render }) => <RenderAsChildren children={render} />,
    ({ render }) => <RenderAsRender render={render} />,
    ({ render }) => <CustomRenderPropName renderItem={render} />
    // ...
  ]}>
  {results => {
    /* Do something with results... */
  }}
</Composer>

Example: Render prop component(s) that produce multiple arguments

Example of how to handle cases when a component passes multiple arguments to its render prop rather than a single argument.

<Composer
  components={[
    <Outer />,
    // Differing render prop signature (multi-arg producers)
    ({ render }) => (
      <ProducesMultipleArgs>
        {(one, two) => render([one, two])}
      </ProducesMultipleArgs>
    ),
    <Inner />
  ]}>
  {([outerResult, [one, two], innerResult]) => {
    /* Do something with results... */
  }}
</Composer>

Limitations

This library only works for render prop components that have a single render prop. So, for instance, this library will not work if your component has an API like the following:

<RenderPropComponent onSuccess={onSuccess} onError={onError} />

Render Order

The first item in the components array will be the outermost component that is rendered. So, for instance, if you pass

<Composer components={[<A/>, <B/>, <C/>]}>

then your tree will render like so:

- A
  - B
    - C

Console Warnings

Render prop components often specify with PropTypes that the render prop is required. When using these components with React Composer, you may get a warning in the console.

One way to eliminate the warnings is to define the render prop as an empty function knowning that Composer will overwrite it with the real render function.

<Composer
  components={[
    <RenderPropComponent {...props} children={() => null} />
  ]}
  // ...
>

Alternatively, you can leverage the flexibility of the props.components as functions API and plug the render function in directly yourself.

<Composer
  components={[
    ({render}) => <RenderPropComponent {...props} children={render} />
  ]}
  // ...
>

Example Usage

Here are some examples of render prop components that benefit from React Composer:

Do you know of a component that you think benefits from React Composer? Open a Pull Request and add it to the list!

Contributing

Are you interested in helping out with this project? That's awesome – thank you! Head on over to the contributing guide to get started.

More Repositories

1

react-request

Declarative HTTP requests for React
JavaScript
362
star
2

redux-resource

3kb resource management for Redux
JavaScript
237
star
3

moment-business

Utilities for work days in Moment. (Western workweeks only.)
JavaScript
99
star
4

gistbook

[No longer hosted] A place to write about technical subjects on the web.
JavaScript
89
star
5

marionette.transition-region

(Unsupported) Because animated view transitions should be easy.
JavaScript
52
star
6

backbone.base-router

A better starting point for building a new Backbone Router.
JavaScript
49
star
7

testing-with-babel

[Don't reference this]: Examples of using Babel with popular testing tools
48
star
8

react-state-context

Lightweight state management using React Context
JavaScript
45
star
9

bestfetch

fetch ⭐️caching ⭐️deduplication
JavaScript
44
star
10

backbone.intercept

Ambient management of link clicks and form submissions.
JavaScript
44
star
11

lrud

A React library for managing focus in TV apps.
TypeScript
40
star
12

router-comparison

WIP: A comparison of client side routers.
38
star
13

knockout-view

(No longer maintained) A bookmarklet that toggles a display of any page's Knockout View Model.
JavaScript
33
star
14

moolah-old

The source code for the original version of Moolah
JavaScript
32
star
15

es6-node-boilerplate

A boilerplate to author, then transpile, Node libraries in ES6.
JavaScript
23
star
16

zero-boilerplate-redux

An example real-world Redux CRUD application with no boilerplate
JavaScript
18
star
17

materialish

React components that loosely follow Material Design
JavaScript
17
star
18

marionette.sliding-view

A sliding Collection View in Marionette.
JavaScript
16
star
19

material-design-icons

A repository for Material Design SVG Icons
HTML
13
star
20

prevent-scroll

[unmaintained] Reliably disable scrolling
JavaScript
12
star
21

simple-jsdom

A simple JSDom configuration for testing libraries.
JavaScript
12
star
22

hsm.js

A minimal hierarchal state machine for Javascript.
JavaScript
12
star
23

query-history

A history with improved query parameter support
TypeScript
12
star
24

bizniz.js

Constant-time business utilities for the western work week
JavaScript
11
star
25

fade-dropdown-menu

A dropdown menu with a fade.
CSS
11
star
26

redux-simple-resource

Project moved --->
JavaScript
11
star
27

latex-to-unicode.js

Convert LaTeX strings to unicode.
JavaScript
10
star
28

standard-resource

WIP: A normalized data store
JavaScript
10
star
29

timeline-utils

WIP: Utilities for working with timeline visualizations
TypeScript
10
star
30

api-pls

Need a backend? Just say please
JavaScript
10
star
31

surfaces.js

Visualize multivariable functions in the browser.
JavaScript
9
star
32

core-hooks

A (small) collection of useful React hooks
TypeScript
9
star
33

backbone.event-spec

An unofficial specification for Backbone Event names.
9
star
34

backbone.simple-auth

A basic cookie-based client-side auth service for Backbone apps.
JavaScript
9
star
35

little-marionette-guides

Short, opinionated guides on some Marionette concepts.
8
star
36

pwa-notes

Notes on building native-feeling Progressive Web Apps
8
star
37

unicode-math.js

Unicode values for math symbols.
JavaScript
7
star
38

backbone.premium-router

(WIP) A premium routing solution for Backbone.
JavaScript
7
star
39

backbone-architecture-101

A short, opinionated guide to Backbone architecture.
7
star
40

moolah-calculators

Calculators for personal finance
JavaScript
7
star
41

react-ui-reference

Reference UI patterns implemented in React
JavaScript
7
star
42

responsive-stylus-mixins

Responsive mixins for Stylus
CSS
7
star
43

react-app-guidelines

Tips that I use when building new React apps
6
star
44

unicode-escape.js

Convert a unicode string to a string of Javascript escape sequences.
JavaScript
6
star
45

backbone.class-event-spec

(WIP) A specification for handling important events in Backbone Classes.
5
star
46

focus

A React library for managing focus in TV apps
JavaScript
5
star
47

cycle-connection-driver

A Cycle.js driver for connection status
JavaScript
5
star
48

stock-market-data

U.S. Stock Market data from Robert Shiller
JavaScript
4
star
49

dom-op-tester

Test DOM ops that may cause reflows with MutationObserver
JavaScript
4
star
50

puppets

A modern Backbone extension.
4
star
51

backbone.overlay-view

A view that covers the app and emits click events.
JavaScript
4
star
52

tangible.js

Create living DOM representations of Javascript objects.
JavaScript
4
star
53

react-media-ui

TypeScript
4
star
54

sliding-dropdown

A simple sliding menu.
CSS
4
star
55

marionette.base-view

A better View for Marionette.
JavaScript
4
star
56

vscode-new-files-from-template

Create VSCode files from a template definition
JavaScript
3
star
57

quantize-number

Quantize a number
JavaScript
3
star
58

i18n-list-generator.js

Generate localized lists
JavaScript
3
star
59

api-pls-example

An api-pls example project
3
star
60

cal

A scheduling app.
JavaScript
2
star
61

example-ts-lib

Example TypeScript library
JavaScript
2
star
62

backbone-orbit

An integration of Backbone and Orbit.js
2
star
63

react-over

Coming soon. A library for positioning elements that appear over the rest of your application
JavaScript
2
star
64

heartbeat.js

Execute a function on an interval
JavaScript
2
star
65

katex-symbols

View all of the symbols that KaTeX supports.
JavaScript
2
star
66

advanced-passport-example

An example application using Passport + social logins, with Postgres for sessions.
JavaScript
2
star
67

pleaserc

Linting configuration for ESLint.
2
star
68

simple-segment-aggregation.js

Aggregate consecutive segments by their events.
JavaScript
2
star
69

two-rotations.js

Rotate vectors about two axes.
JavaScript
2
star
70

js-playground

Just playing around with future JavaScript features...
JavaScript
2
star
71

nearest-periodic-value.js

Find the nearest value of a discrete periodic function, given a point.
JavaScript
2
star
72

jmeas-table-of-contents

[deprecated] see https://github.com/jamesplease/jmeas.com
JavaScript
2
star
73

emoji-clock

An emoji clock web component
JavaScript
2
star
74

backbone.routing-v2

A prototype implementation of Backbone v2 routing and history.
JavaScript
2
star
75

doc-components

React components for documentation sites
CSS
1
star
76

babel-module-inconsistency

This demonstrates the behavior of the es2015 modules=>CJS transform for Babel
JavaScript
1
star
77

cra-template-please

My personal Create React App template
CSS
1
star
78

yearly-to-monthly

Convert yearly values (like salary) to their monthly equivalent
JavaScript
1
star
79

sourcemap-options

The future source map options for the entire grunt-contrib suite
1
star
80

admiral-ui

1
star
81

use-mount-animation

A React Hook for mount and unmount animations
1
star
82

orbit-examples

Examples showing common use cases for Orbit.js
1
star
83

namespace-diff.js

Generate the diff between two namespaces.
JavaScript
1
star
84

katex-support.js

Generate lists of the functions and symbols that KaTeX supports.
JavaScript
1
star
85

desert-racer

A 2D puzzle game written in Unity
C#
1
star
86

moolah-lib

Utilities for finance applications.
TypeScript
1
star
87

react-redux-resource

React bindings for Redux Resource
JavaScript
1
star
88

add-skipping-holes.js

Add values while skipping periodic holes
1
star
89

time-segments.js

Group event data into segments of time.
JavaScript
1
star
90

resource-experiments

Development respository for new resource API
JavaScript
1
star
91

fi-calc-guide

The guide book for FI Calc
JavaScript
1
star
92

simple-css

A straightforward way to write organized & scaleable CSS
1
star
93

moolah

1
star
94

underscore-medley

An assortment of Underscore mixins
JavaScript
1
star
95

simulation-engine

A backtesting and Monte Carlo simulation engine
1
star
96

vscode-snippets

My VSCode snippets
1
star
97

latex-symbols-list.js

A list of LaTeX + AMS symbols.
JavaScript
1
star
98

react-fetcher-app

Development repository for react-fetcher
JavaScript
1
star
99

contained-periodic-values.js

Find how many values of a discrete periodic function are contained in an interval.
JavaScript
1
star
100

consecutive-segments.js

Group consecutive segments.
JavaScript
1
star