{"id":15647514,"url":"https://github.com/ctrlplusb/react-injectables","last_synced_at":"2025-04-30T13:17:42.232Z","repository":{"id":66058714,"uuid":"55504635","full_name":"ctrlplusb/react-injectables","owner":"ctrlplusb","description":"Explicitly inject Components into any part of your React render tree.","archived":false,"fork":false,"pushed_at":"2017-08-03T09:51:54.000Z","size":75,"stargazers_count":44,"open_issues_count":4,"forks_count":6,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-04T20:07:33.608Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","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/ctrlplusb.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-04-05T12:05:56.000Z","updated_at":"2024-04-14T15:05:57.000Z","dependencies_parsed_at":"2023-05-02T01:47:37.926Z","dependency_job_id":null,"html_url":"https://github.com/ctrlplusb/react-injectables","commit_stats":{"total_commits":40,"total_committers":1,"mean_commits":40.0,"dds":0.0,"last_synced_commit":"092c912b99bf84a5387e77d81d6eb074267e8586"},"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ctrlplusb%2Freact-injectables","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ctrlplusb%2Freact-injectables/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ctrlplusb%2Freact-injectables/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ctrlplusb%2Freact-injectables/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ctrlplusb","download_url":"https://codeload.github.com/ctrlplusb/react-injectables/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":242656037,"owners_count":20164431,"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":[],"created_at":"2024-10-03T12:19:43.186Z","updated_at":"2025-03-09T06:33:06.293Z","avatar_url":"https://github.com/ctrlplusb.png","language":"JavaScript","readme":"💀 ___DEPRECATED___ 💀\n\nI have given up on this library. Sorry.\n\nGood news though, it sounds like portals may become a first class citizen when React Fiber lands. 🎉\n\n---\n\n\u003cp align='center'\u003e\n  \u003cimg src='https://raw.githubusercontent.com/ctrlplusb/react-injectables/master/assets/logo.png' width='350'/\u003e\n  \u003cp align='center'\u003eExplicitly inject Components to any part of your React render tree\u003c/p\u003e\n\u003c/p\u003e\n\n[![Travis](https://img.shields.io/travis/ctrlplusb/react-injectables.svg?style=flat-square)](https://travis-ci.org/ctrlplusb/react-injectables) \n[![npm](https://img.shields.io/npm/v/react-injectables.svg?style=flat-square)](http://npm.im/react-injectables)\n[![MIT License](https://img.shields.io/npm/l/react-injectables.svg?style=flat-square)](http://opensource.org/licenses/MIT)\n[![Codecov](https://img.shields.io/codecov/c/github/ctrlplusb/react-injectables.svg?style=flat-square)](https://codecov.io/github/ctrlplusb/react-injectables)\n[![Maintenance](https://img.shields.io/maintenance/yes/2016.svg?style=flat-square)]()\n\n* Uses React's natural render cycles, no DOM hacks.\n* Injections are handled synchronously, no double renders.\n* Supports props pass through to injected Components - behaviour++.\n* No magic strings in your code.  Explicitly define source and target Components.\n* Works with React 0.14 and 15.\n* Extensive test coverage.\n* Micro library. Gzip it to nothingness.\n\n_Note: There have been a lot of releases recently, however, based on usage within my production cases I am happy with where the API is.  Please consider the API in a long term stable condition.  I shall make every attempt from now on to avoid any breaking changes._ \n\n## What is this for?\n\nContent Placeholders, Modals, etc.\n\n## Overview\n\nEnvision you have the following component tree:\n\n```html\n\u003cApp\u003e\n\t\u003cSidebar /\u003e\n\t\u003cMain\u003e\n\t\t\u003cHeader /\u003e\n\t\t{renderedRouteContent}\t\t\t\n\t\t\u003cFooter /\u003e\n\t\u003c/Main\u003e\n\u003c/App\u003e\n```\n\t\nA fairly standard configuration, essentially you have a master application template which each of your routes get rendered in to.  This is handy as you get to share things like your Header, Menu, Footer across all your rendered routes without having to repeat all that code.  But what if you wanted to extend your base template with additional content that is specific to one of the routes being rendered?\n\nFor example, you'll notice the base template holds a handy little `Sidebar` component.  Perhaps you would like a `MyBasketSummary` to be rendered in there whilst the user is viewing the `ProductsRoute`?  Or maybe you would like to inject a new `Button` or `Image` into the `Header` for one of your routes?\n\nHow could you solve these seemingly simple problems?\n\nOne option would be to use react-routers native capability to pass down multiple named components for each of the routes into the base template. For the simple cases we recommend this approach, however, with complex applications having deeply nested routes and component structures this approach may be difficult to manage and could end up in complex props pass-throughs.  \n\nEnter Injectables.\n\nInjectables aims to provide you with a mechanism to explicity define `Injectable` and `Injector` Components.  An `Injector` produces a Component that gets injected into an `Injectable`.\n\nWith Injectables you can easily inject a Component into the `Sidebar` when your `ProductPage` Component gets mounted. Here is a partial example of this:\n\n```javascript\nimport { SidebarInjector } from '../InjectableSidebar';\nimport MyBasket from '../MyBasket';\n\nconst MyBasketSidebarInjection = SidebarInjector(MyBasket);\n\nclass ProductPage extends Component {\n  render() {\n  \treturn (\n  \t\t\u003cdiv\u003e\n         {/* MyBasket will get injected into Sidebar! */}\n         \u003cMyBasketSidebarInjection /\u003e \n  \t\t\n         \u003ch1\u003eProduct Page\u003c/h1\u003e\n         ...\n  \t\t\u003c/div\u003e\n  \t);\n  }\n}\n\nexport default ProductPage;\n```\n\nNow every time the `ProductPage` Component is mounted the `MyBasket` Component will be injected into `Sidebar` Component. Ok, there is a bit of additional setup required in the `Sidebar` Component, but the above is a basic overview of how easy it is to define your injections after the initial configuration.\n\nYes, a bit of fairy dust is involved, but we attempt to keep things as un-magical as possible, pushing for explictness whilst maintaining ease of use.\n\n\n## Usage\n\nFirst install the library.\n\n    npm install react-injectables\n\n### Quick Start\n    \nTo get going there are only 3 steps:\n\n  1. Wrap your application with our `InjectablesProvider`.\n  2. Wrap a Component you would like to _receive_ injected content with our `Injectable` helper. e.g. `Injectable(MainScreen)`\n  4. Wrap a Component you would like to _inject_ with our `Injector` helper. e.g.: `Injector({ into: MainScreen })(MyModal)` \n    \n### Full Tutorial \n\nOk, here's a more detailed run through with example code.\n    \n__Step 1__    \n    \nSomewhere very low down in your application wrap your component tree with our `InjectablesProvider`.  This is the engine that will do all the heavy lifting for you. For example:\n\n```javascript\nimport React from 'react';\nimport ReactDOM from 'react-dom';\nimport { InjectablesProvider } from 'react-injectables';\n    \nReactDOM.render((\n\t\u003cInjectablesProvider\u003e\n\t\t\u003cRouter\u003e\n\t\t\t...\n\t\t\u003c/Router\u003e\n\t\u003c/InjectablesProvider\u003e\n ), document.getElementById('app'));\n```\n\n__Step 2__\n\t \nNow you need to create an `Injectable` Component.  Let's say that you would like to create a `Sidebar` component that you could inject in to. You would do the following:\n\n```javascript\nimport React, { PropTypes } from 'react';\nimport { Injectable, Injector } from 'react-injectables';\n\n// Note the 'injections' prop.  This will contain any injected elements.\nfunction Sidebar({ injections }) {\n  return (\n    \u003cdiv className=\"header\"\u003e\n     {injections}\n    \u003c/div\u003e\n  );\n}\n\n// We wrap our Sidebar component with Injectable. This does all the wiring up for us.\nconst InjectableSidebar = Injectable(Sidebar);\n\n// Create a default Injector configuration for our injectable sidebar.\n// Our Components can use this helper to create injections for the sidebar.\n// NOTE: We are exporting this helper, it will come in handy for the next step.\nexport const SidebarInjector = Injector({ into: InjectableSidebar });\n\nexport default InjectableSidebar;\n```\n\nNotice we also create a default `Injector` configuration for our `InjectableSidebar` called `SidebarInjector`.  This has been exported to allow our other Components to easily import and use this pre-configured helper - it saves us having to repeat this configuration thereby reducing errors.\n    \nWe recommend naming your component files appropriately to indicate that it is indeed an injectable component.  In the above case we named our component file as `InjectableSidebar.js`.  Forming your own conventions around the naming of your injectables and injectors will help.\n    \n__Step 3__\n\nOk, so now you have an `InjectableSidebar` Component and a `SidebarInjector` helper function.  Next up you need to declare a Component that will cause an injection into the Sidebar to occur.\n\n```javascript\nimport React from 'react';\nimport { SidebarInjector } from './InjectableSidebar';\nimport MyBasketView from './MyBasketView';\n\n// Use the SidebarInjector helper to create a Component that will inject the\n// MyBasketView Component into our InjectableSidebar Component.\nconst MyBasketViewSidebarInjection = SidebarInjector(MyBasketView);\n\nclass ProductPage extends Component {\n   ....\n   \n   render() {\n     return (\n     \t\u003cdiv\u003e\n     \t  {/* The injection happens here, i.e. when the ProductPage gets mounted. \n     \t      Nothing actually gets rendered at this location, the Component gets sent to\n             our target Injectable.  In this case it means that MyBasketView will\n             be injected into the Sidebar.\n             Notice how you can also pass down props into your injected component too. */}\n         \u003cMyBasketViewSidebarInjection focusOnProductId={this.props.productId} /\u003e\n     \t\n         \u003ch1\u003eProduct Page\u003c/h1\u003e\n         \n         ...\n     \t\u003c/div\u003e\n     );\n   }\n}\n\nexport default ProductPage;\n```\n \nAnd that's it. Any time the `ProductPage` is mounted it will inject the `MyBasketView` Component into the `Sidebar`.  When the `ProductPage` unmounts, it's respective injected Component will be removed from the `Sidebar`.\n \nAs you can see it's all explicit, so you can follow the import references to find out any relationships.  \n\n## Properties of Injectables and Injectors\n\nHere are a few basic properties you should be aware of:\n\n   * All injection happens within the initial render cycle by react-dom.  Injection does not cause a double render to occur on your `Injectable`s.  This is a result of us trying to intentionally keep injection as \"input to output\" as possible.\n\n   * You can have multiple instances of an `Injectable` rendered in your app.  They will all recieve the same injected content from their respective `Injector`s. \n\n   * You can create multiple `Injector`s Components targetting the same `Injectable` component. For example, you may want to pass in action buttons from different components into an InjectableActions component. \n   \n   * If an Component that is hosting `Injector` is unmounted then the injected Components will automatically be removed from the `Injectable` target. \n   \n   * Any new `Injector`s that are rendered into the tree will automatically have their injected Components passed into any existing `Injectable` targets. i.e. a props update. \n   \n   * `Injector`s are allowed to be mounted before any `Injectable`s.  Once their target `Injectable` Component is mounted then any Components from existing `Injector`s will automatically be passed into the newly mounted `Injectable`.\n\n## Examples\n\nAt the moment there is only one example, using react-router.  Check out the examples folder.  I wouldn't recommend running it yet as I have yet to add any style to it, but it will execute if you try. :)\n\n\n## Some other considerations.\n\n__I am using redux or another flux-like library__\n\nThen perhaps you should try and use their respective action flows in order to control the \"injection\" of your content in a manner that follows their uni-directional flows. \n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fctrlplusb%2Freact-injectables","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fctrlplusb%2Freact-injectables","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fctrlplusb%2Freact-injectables/lists"}