You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
perf(api): Massive simplification to API, along with guards and 100% test cov.
The API has been refocused to allow for the injection of Components of any type
(i.e. class/stateless/createClass). The Provider has been renamed to make it
more explicit, and the Injector API has been greatly simplified. A lot more
invariant based checks have been added to the project and we have achieved
full test coverage.
closes#2closes#3
BREAKING CHANGE: Provider renamed to InjectableProvider.
BREAKING CHANGE: The Injector helper has been greatly simplified. Instead of
wrapping a component that will host the injection, it rather produces an
injection component which you can render into any component that you would
like to initiate an injection. This produces a much cleaner API and allows
you to easily pass down specific props to the component that will be injected.
Please look at the updated readme for example usage.
Tiny, and the only dependency is a peer dependency of React.
13
-
14
-
### Warning
15
-
16
-
I am actively developing this project whilst applying it to a production use-case. This is exposing the limitations of the API pretty fast requiring that I do quick updates. Expect the versions to bump excessively over the next couple of weeks, but I will stabilise it as quickly as I can. I'm not a fan of 0.x.x beta releases and don't mind big numbers. I like that each version I release clearly indicates breaking changes. This message will disappear as soon as I believe the API will remain stable for an extended period of time.
12
+
This is a teeny tiny React library - it's almost unnoticable when gzipped.
17
13
18
14
## What is this for?
19
15
20
-
Placeholders, Modals, etc etc.
16
+
Placeholders, Modals, etc.
21
17
22
18
## Overview
23
19
@@ -44,26 +40,34 @@ One option would be to use react-routers native capability to pass down multiple
44
40
45
41
Enter Injectables.
46
42
47
-
Injectables aims to provide you with a mechanism to explicity define an Injectable target and Injector source component(s).
43
+
Injectables 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`.
48
44
49
-
With Injectables you can easily inject into `Sidebar`from your `ProductPage`doing something similar to the following:
45
+
With Injectables you can easily inject a Component into the `Sidebar`when your `ProductPage`Component gets mounted. Here is a partial example of this:
Now every time `ProductPage` is rendered onto the page the `MyBasketSummary`will be injected into `Sidebar`. Ok, there is a tiny bit of additional setup. But it's quick sticks to get going.
68
+
Now 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, but the above is a basic overview of how easy it is to define your injections after the initial configuration.
65
69
66
-
Fairy dust is involved, but we attempt to keep things as un-magical as possible, keeping things explict, whilst also easy to use.
70
+
Yep, some fairy dust is involved, but we attempt to keep things as un-magical as possible, pushing for explictness whilst keeping it easy to use.
67
71
68
72
69
73
## Usage
@@ -76,48 +80,45 @@ First install the library.
76
80
77
81
To get going there are only 3 steps:
78
82
79
-
1. Wrap your application with our `Provider`.
80
-
2. Wrap a component you would like to _receive_ content with our `Injectable`. e.g. `Injectable(Sidebar)`
81
-
4. Wrap a component you would like to _produce_ content with our `Injector`. e.g.: `Injector({ to: InjectableSidebar, inject: () => <MyBasketsView>)(ProductPage)`
83
+
1. Wrap your application with our `InjectablesProvider`.
84
+
2. Wrap a Component you would like to _receive_injected content with our `Injectable` helper. e.g. `Injectable(MainScreen)`
85
+
4. Wrap a Component you would like to _inject_with our `Injector` helper. e.g.: `Injector({ into: MainScreen })(MyModal)`
82
86
83
87
### Full Tutorial
84
88
85
89
Ok, here's a more detailed run through with example code.
86
90
87
91
__Step 1__
88
92
89
-
Somewhere very low down in your application wrap your component tree with our `Provider`. This is the engine that will do all the heavy lifting for you. For example:
93
+
Somewhere 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:
_Note:_ If you already have another component with the name of `Provider` in your app (think redux), then you can rename the import, like so:
106
-
`import { Provider as InjectablesProvider } from 'react-injectables';`
107
-
108
109
__Step 2__
109
110
110
-
Now 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:
111
+
Now 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:
111
112
112
113
```javascript
113
114
importReact, { PropTypes } from'react';
114
115
import { Injectable } from'react-injectables';
115
116
116
-
// Note the 'injected' prop. This will contain any injected elements.
117
-
functionSidebar({ injected }) {
117
+
// Note the 'injections' prop. This will contain any injected elements.
118
+
functionSidebar({ injections }) {
118
119
return (
119
120
<div className="header">
120
-
{injected}
121
+
{injections}
121
122
</div>
122
123
);
123
124
}
@@ -132,45 +133,43 @@ __Step 3__
132
133
133
134
Ok, so you have an `InjectableSidebar` now, but you need to declare the components that will inject content in to it.
134
135
135
-
You need to make use of our `Injector`, wrapping your component, whilst also providing the target injectable component and the elements that you wish to inject.
136
+
You need to make use of our `Injector`, wrapping the Component you would like to inject, whilst also providing the target `Injectable` Component you created.
136
137
137
138
```javascript
138
139
importReactfrom'react';
139
140
import { Injector } from'react-injectables';
140
141
importInjectableSidebarfrom'./InjectableSidebar';
141
-
importBasketViewPagefrom'./BasketViewPage';
142
+
importMyBasketViewfrom'./MyBasketView';
143
+
144
+
// This sets up our injection.
145
+
constMyBasketViewSidebarInjection=Injector({
146
+
into: InjectableSidebar // The target Injectable Component. The actual Component - explicit. :)
147
+
})(MyBasketView); // The Component you would like to be injected.
142
148
143
149
classProductsPageextendsComponent {
144
150
....
151
+
152
+
render() {
153
+
return (
154
+
<div>
155
+
{/* The injection! Nothing actually gets rendered here, it gets sent to
156
+
our target Injectable. In this case it means that MyBasketView will
157
+
be injected into the Sidebar.
158
+
Notice how you can also pass down props into your injected component too. */}
to: InjectableSidebar, // You have to specify the actual Injectable Component. Explicit.
155
-
inject: Inject // The inject function or a React Element.
156
-
})(ProductsPage);
167
+
exportdefaultProductsPage;
157
168
```
158
169
159
-
The `inject` property argument for the `Injector` accepts either of two things:
160
-
161
-
* A function with a `props` argument that when executed will return a React Element. i.e. a stateless functional component. It will recieve the same props that will be passed into the component being wrapped by the `Injector`. If you wrap your component with multiple higher order functions/components then please make sure that `Injector` is the first of the functions used to wrap your component. For e.g.
162
-
```javascript
163
-
exportdefaultcompose( // executes last to first.
164
-
Connect(stateM, propsM),
165
-
Injector(args)
166
-
)(ProductsPage);
167
-
```
168
-
169
-
* A React element. This works, however the element is created up front before it is even needed. Also you lose the capability to interogate any props that may have been passed into your component.
170
-
171
170
---
172
171
173
-
And that's it. Any time the `ProductsPage` is rendered it will inject it's content into the `Sidebar`. When it unmounts, it's injected elements will be removed from the `Sidebar`.
172
+
And that's it. Any time the `ProductsPage` is mounted it will inject the `MyBasketView` Component into the `Sidebar`. When it unmounts, the respective Component will be removed from the `Sidebar`.
174
173
175
174
As you can see it's all explicit, so you can follow the import references to find out any relationships.
176
175
@@ -180,17 +179,17 @@ You will need to repeat steps 2 and 3 for any set of Injectable targets and Inje
180
179
181
180
Here are a few basic properties you should be aware of:
182
181
183
-
* All injection happens within the initial render cycle by react-dom. Injection does not cause a double render to occur. This is a result of us trying to intentionally keep injection as "uni-directional" / "input -> output" as possible.
182
+
* 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.
184
183
185
-
* You can have multiple instances of an Injectable rendered in your app. They will all recieve the same injected content from their respective Injectors.
184
+
* 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.
186
185
187
-
* You can create multiple Injectors components targetting the same Injectable component. The rendered Injectors shall have their injected elements collected and passed through to the target Injectable. For example, you may want to pass in action buttons from different components into an InjectableActions component.
186
+
* 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.
188
187
189
-
* If an Injector is removed from the tree then it's injected elements will automatically be removed from the Injectable target.
188
+
* If an Component that is hosting `Injector` is unmounted then the injected Components will automatically be removed from the `Injectable` target.
190
189
191
-
* Any new Injectors that are rendered into the tree will automatically have their injected content rendered within any rendered Injectable target.
190
+
* 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.
192
191
193
-
*Injectors are allowed to be rendered before any Injectables. Once their target Injectable Component is rendered then any content from existing the Injectors will automatically be rendered within the newly rendered Injectable.
192
+
*`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`.
0 commit comments