{"id":13481238,"url":"https://github.com/jamesplease/react-composer","last_synced_at":"2025-05-15T15:06:29.155Z","repository":{"id":28488100,"uuid":"118290693","full_name":"jamesplease/react-composer","owner":"jamesplease","description":"Compose render prop components","archived":false,"fork":false,"pushed_at":"2022-04-28T19:21:52.000Z","size":79,"stargazers_count":609,"open_issues_count":3,"forks_count":17,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-05-05T18:37:40.767Z","etag":null,"topics":["props","react","render"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jamesplease.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-01-20T23:57:29.000Z","updated_at":"2025-05-04T12:14:46.000Z","dependencies_parsed_at":"2022-08-07T13:15:56.160Z","dependency_job_id":null,"html_url":"https://github.com/jamesplease/react-composer","commit_stats":null,"previous_names":["jmeas/react-composer"],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamesplease%2Freact-composer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamesplease%2Freact-composer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamesplease%2Freact-composer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamesplease%2Freact-composer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jamesplease","download_url":"https://codeload.github.com/jamesplease/react-composer/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253391251,"owners_count":21900943,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["props","react","render"],"created_at":"2024-07-31T17:00:49.982Z","updated_at":"2025-05-15T15:06:29.133Z","avatar_url":"https://github.com/jamesplease.png","language":"JavaScript","readme":"# React Composer\n\n[![Travis build status](http://img.shields.io/travis/jamesplease/react-composer.svg?style=flat)](https://travis-ci.org/jamesplease/react-composer)\n[![npm version](https://img.shields.io/npm/v/react-composer.svg)](https://www.npmjs.com/package/react-composer)\n[![npm downloads](https://img.shields.io/npm/dm/react-composer.svg)](https://www.npmjs.com/package/react-composer)\n[![Test Coverage](https://coveralls.io/repos/github/jamesplease/react-composer/badge.svg?branch=master)](https://coveralls.io/github/jamesplease/react-composer?branch=master)\n[![gzip size](http://img.badgesize.io/https://unpkg.com/react-composer/dist/react-composer.min.js?compression=gzip)](https://unpkg.com/react-composer/dist/react-composer.min.js)\n\nCompose [render prop](https://reactjs.org/docs/render-props.html) components.\n\n## Motivation\n\nRender props are great. Using a component with a render prop looks like the following:\n\n```jsx\n\u003cRenderPropComponent {...config}\u003e\n  {result =\u003e \u003cMyComponent result={result} /\u003e}\n\u003c/RenderPropComponent\u003e\n```\n\nSometimes you need the result of multiple render prop components inside of `MyComponent`. This\ncan get messy.\n\n```jsx\n\u003cRenderPropComponent {...config}\u003e\n  {resultOne =\u003e (\n    \u003cRenderPropComponent {...configTwo}\u003e\n      {resultTwo =\u003e (\n        \u003cRenderPropComponent {...configThree}\u003e\n          {resultThree =\u003e (\n            \u003cMyComponent results={{ resultOne, resultTwo, resultThree }} /\u003e\n          )}\n        \u003c/RenderPropComponent\u003e\n      )}\n    \u003c/RenderPropComponent\u003e\n  )}\n\u003c/RenderPropComponent\u003e\n```\n\nNesting render prop components leads to rightward drift of your code. Use React Composer to\nprevent that drift.\n\n```jsx\nimport Composer from 'react-composer';\n\n\u003cComposer\n  components={[\n    \u003cRenderPropComponent {...configOne} /\u003e,\n    \u003cRenderPropComponent {...configTwo} /\u003e,\n    \u003cRenderPropComponent {...configThree} /\u003e\n  ]}\u003e\n  {([resultOne, resultTwo, resultThree]) =\u003e (\n    \u003cMyComponent results={{ resultOne, resultTwo, resultThree }} /\u003e\n  )}\n\u003c/Composer\u003e;\n```\n\n## Installation\n\nInstall using [npm](https://www.npmjs.com):\n\n```\nnpm install react-composer\n```\n\nor [yarn](https://yarnpkg.com/):\n\n```\nyarn add react-composer\n```\n\n## API\n\nThis library has one, default export: `Composer`.\n\n### `\u003cComposer /\u003e`\n\nCompose multiple render prop components together. The props are as\nfollows:\n\n### `props.children`\n\nA render function that is called with an array of results accumulated from the render prop components.\n\n```jsx\n\u003cComposer components={[]}\u003e\n  {results =\u003e {\n    /* Do something with results... Return a valid React element. */\n  }}\n\u003c/Composer\u003e\n```\n\n### `props.components`\n\nThe render prop components to compose. This is an array of [React elements](https://reactjs.org/docs/glossary.html#elements) and/or render functions that are invoked with a render function and the currently accumulated results.\n\n```jsx\n\u003cComposer\n  components={[\n    // React elements may be passed for basic use cases\n    // props.children will be provided via React.cloneElement\n    \u003cOuter /\u003e,\n\n    // Render functions may be passed for added flexibility and control\n    ({ results, render }) =\u003e (\n      \u003cMiddle previousResults={results} children={render} /\u003e\n    )\n  ]}\u003e\n  {([outerResult, middleResult]) =\u003e {\n    /* Do something with results... Return a valid React element. */\n  }}\n\u003c/Composer\u003e\n```\n\n\u003e **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.\n\n#### `props.components` as render functions\n\nA render function may be passed instead of a React element for added flexibility.\n\nRender functions provided must return a valid React element. Render functions will be invoked with an object containing 2 properties:\n\n1.  `results`: The currently accumulated results. You can use this for render prop components which depend on the results of other render prop components.\n2.  `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`.\n\n```jsx\n\u003cComposer\n  components={[\n    // props.components may contain both elements and render functions\n    \u003cOuter /\u003e,\n    ({ /* results, */ render }) =\u003e \u003cSomeComponent children={render} /\u003e\n  ]}\u003e\n  {results =\u003e {\n    /* Do something with results... */\n  }}\n\u003c/Composer\u003e\n```\n\n## Examples and Guides\n\n### Example: Render prop component(s) depending on the result of other render prop component(s)\n\n```jsx\n\u003cComposer\n  components={[\n    \u003cOuter /\u003e,\n    ({ results: [outerResult], render }) =\u003e (\n      \u003cMiddle fromOuter={outerResult} children={render} /\u003e\n    ),\n    ({ results, render }) =\u003e (\n      \u003cInner fromOuterAndMiddle={results} children={render} /\u003e\n    )\n    // ...\n  ]}\u003e\n  {([outerResult, middleResult, innerResult]) =\u003e {\n    /* Do something with results... */\n  }}\n\u003c/Composer\u003e\n```\n\n### Example: Render props named other than `props.children`.\n\nBy default, `\u003cComposer /\u003e` will enhance your React elements with `props.children`.\n\nRender 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:\n\n```jsx\n\u003cComposer\n  components={[\n    // Support varying named render props\n    \u003cRenderAsChildren /\u003e,\n    ({ render }) =\u003e \u003cRenderAsChildren children={render} /\u003e,\n    ({ render }) =\u003e \u003cRenderAsRender render={render} /\u003e,\n    ({ render }) =\u003e \u003cCustomRenderPropName renderItem={render} /\u003e\n    // ...\n  ]}\u003e\n  {results =\u003e {\n    /* Do something with results... */\n  }}\n\u003c/Composer\u003e\n```\n\n### Example: Render prop component(s) that produce multiple arguments\n\nExample of how to handle cases when a component passes multiple arguments to its render prop rather than a single argument.\n\n```jsx\n\u003cComposer\n  components={[\n    \u003cOuter /\u003e,\n    // Differing render prop signature (multi-arg producers)\n    ({ render }) =\u003e (\n      \u003cProducesMultipleArgs\u003e\n        {(one, two) =\u003e render([one, two])}\n      \u003c/ProducesMultipleArgs\u003e\n    ),\n    \u003cInner /\u003e\n  ]}\u003e\n  {([outerResult, [one, two], innerResult]) =\u003e {\n    /* Do something with results... */\n  }}\n\u003c/Composer\u003e\n```\n\n### Limitations\n\nThis library only works for render prop components that have a single render\nprop. So, for instance, this library will not work if your component has an API like the following:\n\n```jsx\n\u003cRenderPropComponent onSuccess={onSuccess} onError={onError} /\u003e\n```\n\n### Render Order\n\nThe first item in the `components` array will be the outermost component that is rendered. So, for instance,\nif you pass\n\n```jsx\n\u003cComposer components={[\u003cA/\u003e, \u003cB/\u003e, \u003cC/\u003e]}\u003e\n```\n\nthen your tree will render like so:\n\n```\n- A\n  - B\n    - C\n```\n\n### Console Warnings\n\nRender prop components often specify with [PropTypes](https://reactjs.org/docs/typechecking-with-proptypes.html)\nthat the render prop is required. When using these components with React Composer, you may get a warning in the\nconsole.\n\nOne way to eliminate the warnings is to define the render prop as an empty function knowning that `Composer` will\noverwrite it with the real render function.\n\n```jsx\n\u003cComposer\n  components={[\n    \u003cRenderPropComponent {...props} children={() =\u003e null} /\u003e\n  ]}\n  // ...\n\u003e\n```\n\nAlternatively, you can leverage the flexibility of the `props.components` as functions API and plug the render function in directly yourself.\n\n```jsx\n\u003cComposer\n  components={[\n    ({render}) =\u003e \u003cRenderPropComponent {...props} children={render} /\u003e\n  ]}\n  // ...\n\u003e\n```\n\n### Example Usage\n\nHere are some examples of render prop components that benefit from React Composer:\n\n* React's [Context API](https://reactjs.org/docs/context.html). See [this example](https://codesandbox.io/s/92pj14134y) by [Kent Dodds](https://twitter.com/kentcdodds).\n* [React Request](https://github.com/jamesplease/react-request)\n* Apollo's [Query component](https://www.apollographql.com/docs/react/essentials/queries.html#basic)\n\nDo you know of a component that you think benefits from React Composer? Open a Pull Request and add it to the list!\n\n## Contributing\n\nAre you interested in helping out with this project? That's awesome – thank you! Head on over to\n[the contributing guide](./CONTRIBUTING.md) to get started.\n","funding_links":[],"categories":["Components","JavaScript","List","Libraries"],"sub_categories":["Composition"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjamesplease%2Freact-composer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjamesplease%2Freact-composer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjamesplease%2Freact-composer/lists"}