@adimm/x-injection-reactjs 0.3.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +188 -103
- package/dist/index.cjs +78 -151
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +52 -148
- package/dist/index.d.ts +52 -148
- package/dist/index.js +64 -139
- package/dist/index.js.map +1 -1
- package/package.json +13 -13
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<h1 align="center">
|
|
2
2
|
xInjection ReactJS <a href="https://www.npmjs.com/package/@adimm/x-injection-reactjs" target="__blank"><img src="https://badgen.net/npm/v/@adimm/x-injection-reactjs"></a>
|
|
3
|
-
<img src="https://badgen.net/npm/license/@adimm/x-injection-reactjs">
|
|
4
3
|
<a href="https://app.codecov.io/gh/AdiMarianMutu/x-injection-reactjs" target="__blank"><img src="https://badgen.net/codecov/c/github/AdiMarianMutu/x-injection-reactjs"></a>
|
|
4
|
+
<img src="https://badgen.net/npm/license/@adimm/x-injection-reactjs">
|
|
5
5
|
</h1>
|
|
6
6
|
|
|
7
7
|
<p align="center">
|
|
@@ -19,24 +19,32 @@ xInjection ReactJS <a href="https://www.npmjs.com/package/@adimm/x-injection-rea
|
|
|
19
19
|
- [Installation](#installation)
|
|
20
20
|
- [TypeScript Configuration](#typescript-configuration)
|
|
21
21
|
- [Getting Started](#getting-started)
|
|
22
|
-
- [
|
|
23
|
-
- [
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
- [Quick Start](#quick-start)
|
|
23
|
+
- [Conventions](#conventions)
|
|
24
|
+
- [Component Module](#component-module)
|
|
25
|
+
- [Component Service](#component-service)
|
|
26
|
+
- [How to tie a `ProviderModule` to a `Component`?](#how-to-tie-a-providermodule-to-a-component)
|
|
27
|
+
- [Is your component re-usable?](#is-your-component-re-usable)
|
|
28
|
+
- [Yes](#yes)
|
|
29
|
+
- [No](#no)
|
|
30
|
+
- [How to control a Child component providers from Parent component?](#how-to-control-a-child-component-providers-from-parent-component)
|
|
31
|
+
- [Override the entire Child Module](#override-the-entire-child-module)
|
|
32
|
+
- [Override only specific Child Providers](#override-only-specific-child-providers)
|
|
26
33
|
- [Hook Injection](#hook-injection)
|
|
27
34
|
- [Examples](#examples)
|
|
28
35
|
- [Composable components](#composable-components)
|
|
29
36
|
- [Unit Tests](#unit-tests)
|
|
30
37
|
- [Documentation](#documentation)
|
|
31
38
|
- [Contributing](#contributing)
|
|
39
|
+
- [Credits](#credits)
|
|
32
40
|
|
|
33
41
|
## Overview
|
|
34
42
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
Each `ProviderModule` manages its _own_ container, supporting easy **decoupling** and _explicit_ control over which providers are **exported** and **imported** across modules. The global **[AppModule](https://adimarianmutu.github.io/x-injection/variables/AppModule.html)** is always available, ensuring a seamless foundation for your application's DI needs.
|
|
43
|
+
This is the _official_ [ReactJS](https://react.dev/) implementation of the [xInjection](https://github.com/AdiMarianMutu/x-injection) library.
|
|
38
44
|
|
|
39
|
-
>
|
|
45
|
+
> [!Warning]
|
|
46
|
+
>
|
|
47
|
+
> The usage of the `base` library will not be explained here, I'll assume you already know how to use the `xInjection` library, if that's not the case, please refer to the `xInjection` [Gettng Started](https://github.com/AdiMarianMutu/x-injection?tab=readme-ov-file#getting-started) section.
|
|
40
48
|
|
|
41
49
|
## Installation
|
|
42
50
|
|
|
@@ -52,6 +60,8 @@ Then install `xInjection` for React:
|
|
|
52
60
|
npm i @adimm/x-injection-reactjs
|
|
53
61
|
```
|
|
54
62
|
|
|
63
|
+
> [!Note]
|
|
64
|
+
>
|
|
55
65
|
> You may also have to install the parent library via `npm i @adimm/x-injection`
|
|
56
66
|
|
|
57
67
|
### TypeScript Configuration
|
|
@@ -69,126 +79,192 @@ Add the following options to your `tsconfig.json` to enable decorator metadata:
|
|
|
69
79
|
|
|
70
80
|
## Getting Started
|
|
71
81
|
|
|
72
|
-
|
|
82
|
+
### Quick Start
|
|
73
83
|
|
|
74
|
-
|
|
84
|
+
```tsx
|
|
85
|
+
const UserDashboardModuleBp = ProviderModule.blueprint({
|
|
86
|
+
id: 'ComponentUserDashboardModule',
|
|
87
|
+
imports: [UserModule],
|
|
88
|
+
exports: [UserModule],
|
|
89
|
+
});
|
|
75
90
|
|
|
76
|
-
|
|
91
|
+
const UserDashboard = provideModuleToComponent(UserDashboardModuleBp, () => {
|
|
92
|
+
const userService = useInject(UserService);
|
|
77
93
|
|
|
78
|
-
|
|
94
|
+
return (
|
|
95
|
+
<h1>
|
|
96
|
+
Hello {userService.firstName} {userService.lastName}!
|
|
97
|
+
</h1>
|
|
98
|
+
);
|
|
99
|
+
});
|
|
79
100
|
|
|
80
|
-
|
|
81
|
-
|
|
101
|
+
const App = () => {
|
|
102
|
+
return (
|
|
103
|
+
<>
|
|
104
|
+
<Navbar />
|
|
105
|
+
<UserDashboard />
|
|
106
|
+
<Footer />
|
|
107
|
+
</>
|
|
108
|
+
);
|
|
109
|
+
};
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Conventions
|
|
82
113
|
|
|
83
|
-
|
|
114
|
+
Before continuing you should read also the [Conventions](https://github.com/AdiMarianMutu/x-injection?tab=readme-ov-file#conventions) section of the _parent_ library.
|
|
84
115
|
|
|
85
|
-
### Component
|
|
116
|
+
### Component Module
|
|
86
117
|
|
|
87
|
-
|
|
118
|
+
You should create a separate file which you'll use to declare the `blueprint` of the _component_ `module`:
|
|
88
119
|
|
|
89
|
-
|
|
120
|
+
`user-dashboard/user-dashboard.module.ts`
|
|
90
121
|
|
|
91
122
|
```ts
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
123
|
+
export const UserDashboardModuleBp = ProviderModule.blueprint({
|
|
124
|
+
id: 'ComponentUserDashboardModule',
|
|
125
|
+
...
|
|
126
|
+
});
|
|
127
|
+
```
|
|
96
128
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
}
|
|
129
|
+
> [!Note]
|
|
130
|
+
>
|
|
131
|
+
> You should also prefix the `id` of the `blueprints` with `Component` as this will help you to debug your app much more easier when something goes wrong.
|
|
101
132
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
});
|
|
133
|
+
### Component Service
|
|
134
|
+
|
|
135
|
+
You should create a separate file which you'll use to declare the _(main)_ `service` of the _component_.
|
|
106
136
|
|
|
107
|
-
|
|
137
|
+
`user-dashboard/user-dashboard.service.ts`
|
|
138
|
+
|
|
139
|
+
```ts
|
|
140
|
+
@Injectable()
|
|
141
|
+
export class UserDashboardService {
|
|
108
142
|
firstName: string;
|
|
109
143
|
lastName: string;
|
|
110
144
|
}
|
|
111
145
|
```
|
|
112
146
|
|
|
113
|
-
|
|
147
|
+
### How to tie a `ProviderModule` to a `Component`?
|
|
148
|
+
|
|
149
|
+
You first have to either create a `module` or `blueprint`, most of the times you'll use the `blueprint` option, if you are asking yourself how you should decide:
|
|
150
|
+
|
|
151
|
+
#### Is your component re-usable?
|
|
152
|
+
|
|
153
|
+
> Will you have **more** than **one** instance of that component?
|
|
114
154
|
|
|
115
|
-
|
|
155
|
+
##### Yes
|
|
116
156
|
|
|
117
|
-
|
|
157
|
+
- Then you have to use a `blueprint`, the reason can be understood by reading [this](https://github.com/AdiMarianMutu/x-injection?tab=readme-ov-file#import-behavior).
|
|
118
158
|
|
|
119
|
-
|
|
159
|
+
##### No
|
|
160
|
+
|
|
161
|
+
- Then you have to use a raw `module`, the reason is the opposite of the `blueprint` motive.
|
|
162
|
+
|
|
163
|
+
> [!Tip] If the above explaination is clear, please skip to the next section, otherwise keep reading.
|
|
164
|
+
|
|
165
|
+
Imagine that we have a `Button` component, clearly we'll have more than one instance of that component, this means that **each** _instance_ of the `Button` component must have its own `module`, where all the `singletons` will act as singletons _only inside_ the component **instance**.
|
|
166
|
+
|
|
167
|
+
> Therefore we leverage the `blueprint` _import_ behavior to achieve that naturally without additional overhead.
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
After you created the `component module`, you can provide it to the actual component by using the [provideModuleToComponent](https://adimarianmutu.github.io/x-injection-reactjs/functions/provideModuleToComponent.html) _([HoC](https://legacy.reactjs.org/docs/higher-order-components.html))_ `method`.
|
|
120
172
|
|
|
121
173
|
```tsx
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
174
|
+
const UserDashboard = provideModuleToComponent(UserDashboardModuleBp, (props: UserDashboardProps) => {
|
|
175
|
+
...
|
|
176
|
+
});
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### How to control a Child component providers from Parent component?
|
|
180
|
+
|
|
181
|
+
If you need this design pattern, it is very easy to implement with `xInjection`, you actually have 2 options:
|
|
125
182
|
|
|
126
|
-
|
|
127
|
-
userService.lastName = lastName;
|
|
183
|
+
#### Override the entire Child Module
|
|
128
184
|
|
|
129
|
-
|
|
185
|
+
Let's say that the `Child` component has this `module`:
|
|
186
|
+
|
|
187
|
+
```ts
|
|
188
|
+
const ChildModuleBp = ProviderModule.blueprint({
|
|
189
|
+
id: 'ComponentChildModule',
|
|
190
|
+
providers: [ChildService],
|
|
191
|
+
exports: [ChildService],
|
|
130
192
|
});
|
|
193
|
+
```
|
|
131
194
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
195
|
+
What you can now do is to provide the `ChildService` from the `Parent` component, like this:
|
|
196
|
+
|
|
197
|
+
```ts
|
|
198
|
+
const ParentModuleBp = ProviderModule.blueprint({
|
|
199
|
+
id: 'ComponentParentModule',
|
|
200
|
+
providers: [ParentService, ChildService],
|
|
201
|
+
exports: [ParentService, ChildService],
|
|
202
|
+
});
|
|
138
203
|
```
|
|
139
204
|
|
|
140
|
-
|
|
205
|
+
Then, when you are rendering the `Child` component from **within** the `Parent` component:
|
|
141
206
|
|
|
142
|
-
|
|
207
|
+
```ts
|
|
208
|
+
const ParentComponent = provideModuleToComponent(ParentModuleBp, ({ module }) => {
|
|
209
|
+
// the `module` prop is always available and automatically injected into the `props` object.
|
|
143
210
|
|
|
144
|
-
|
|
211
|
+
return <ChildComponent module={module} />;
|
|
212
|
+
});
|
|
213
|
+
```
|
|
145
214
|
|
|
146
|
-
|
|
147
|
-
export function UserInfo({ firstName, lastName }: UserInfoProps) {
|
|
148
|
-
const userService = useInject(UserService);
|
|
215
|
+
Now the `ChildComponent` will be instantiated with the `module` received from the `ParentComponent`, therefore it'll use the `ChildService` managed into the `ParentModule`.
|
|
149
216
|
|
|
150
|
-
|
|
151
|
-
|
|
217
|
+
> [!Tip]
|
|
218
|
+
>
|
|
219
|
+
> This is perfect to use when you are writing _unit tests_ and you want to mock an entire component `module`
|
|
152
220
|
|
|
153
|
-
|
|
154
|
-
}
|
|
221
|
+
#### Override only specific Child Providers
|
|
155
222
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
}
|
|
223
|
+
> This is the approach which you should strive to use most of the times as it is less prone to _"human error"_ than overriding the entire module.
|
|
224
|
+
|
|
225
|
+
Let's re-use the same example as the one from the above, the `ParentModule`:
|
|
226
|
+
|
|
227
|
+
```ts
|
|
228
|
+
const ParentModuleBp = ProviderModule.blueprint({
|
|
229
|
+
id: 'ComponentParentModule',
|
|
230
|
+
providers: [ParentService, ChildService],
|
|
231
|
+
exports: [ParentService, ChildService],
|
|
232
|
+
});
|
|
166
233
|
```
|
|
167
234
|
|
|
168
|
-
|
|
235
|
+
And now the rendering part:
|
|
169
236
|
|
|
170
|
-
|
|
237
|
+
```ts
|
|
238
|
+
const ParentComponent = provideModuleToComponent(ParentModuleBp, () => {
|
|
239
|
+
// notice that we are not using the `module` prop anymore.
|
|
240
|
+
const childService = useInject(ChildService);
|
|
171
241
|
|
|
172
|
-
|
|
242
|
+
return <ChildComponent inject={[{ provide: ChildService, useValue: childService }]} />;
|
|
243
|
+
});
|
|
244
|
+
```
|
|
173
245
|
|
|
174
|
-
|
|
246
|
+
By using the `inject` prop _(which as the `module` prop is always available)_ you'll _"swap"_ the `ChildService` provider with a [ProviderValueToken](https://adimarianmutu.github.io/x-injection/types/ProviderValueToken.html) which provides the `ChildService` **instance** instantiated by the `ParentComponent`.
|
|
175
247
|
|
|
176
|
-
|
|
248
|
+
> [!Note]
|
|
249
|
+
>
|
|
250
|
+
> If you are asking yourself `Why would I want to do that?`, that's a valid question, and most of the times you'll **not** need this feature, but sometimes, when you _compose_ components, being able to control the _providers_ of the children components becomes very useful. Check the [Composable Components](#composable-components) example to understand.
|
|
177
251
|
|
|
178
|
-
|
|
252
|
+
### Hook Injection
|
|
253
|
+
|
|
254
|
+
You already have seen in action the low-level [useInject](https://adimarianmutu.github.io/x-injection-reactjs/functions/useInject.html) hook _(take a look also at the [useInjectMany](https://adimarianmutu.github.io/x-injection-reactjs/functions/useInjectMany.html) hook)_. It is quite useful when you just have to inject quickly some dependencies into a component quite simple.
|
|
179
255
|
|
|
180
|
-
|
|
256
|
+
But, as your UI will _grow_, you'll soon discover that you may inject _more_ dependencies into a component, or even in multiple components, therefore you'll end up writing a lot of duplicated code, well, as per the [DRY](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself#:~:text=%22Don't%20repeat%20yourself%22,redundancy%20in%20the%20first%20place.) principle, we want to _avoid_ that.
|
|
181
257
|
|
|
182
|
-
|
|
258
|
+
This means that we can actually use the [hookFactory](https://adimarianmutu.github.io/x-injection-reactjs/functions/hookFactory.html) method to compose a _custom_ hook with access to any dependency available in the component module.
|
|
183
259
|
|
|
184
260
|
```ts
|
|
185
261
|
// The `HookWithDeps` generic type will help
|
|
186
262
|
// in making sure that the `useGenerateUserFullName` hooks params are correctly visible.
|
|
187
263
|
// The 1st generic param must be the hook params (Like `UserInfoProps`)
|
|
188
|
-
// and
|
|
264
|
+
// and the 2nd generic param must be an `array` with the providers type.
|
|
189
265
|
const useGenerateUserFullName = hookFactory({
|
|
190
266
|
// The `use` property is where you write your hook implementation.
|
|
191
|
-
use: ({ firstName, lastName, deps: [userService] }: HookWithDeps<UserInfoProps, UserService>) => {
|
|
267
|
+
use: ({ firstName, lastName, deps: [userService] }: HookWithDeps<UserInfoProps, [UserService]>) => {
|
|
192
268
|
userService.firstName = firstName;
|
|
193
269
|
userService.lastName = lastName;
|
|
194
270
|
|
|
@@ -202,7 +278,7 @@ const useGenerateUserFullName = hookFactory({
|
|
|
202
278
|
});
|
|
203
279
|
```
|
|
204
280
|
|
|
205
|
-
Now you can use it in inside any component which
|
|
281
|
+
Now you can use it in inside any component which is using a `module` which can provide the `UserService`.
|
|
206
282
|
|
|
207
283
|
```tsx
|
|
208
284
|
export function UserInfo({ firstName, lastName }: UserInfoProps) {
|
|
@@ -212,6 +288,10 @@ export function UserInfo({ firstName, lastName }: UserInfoProps) {
|
|
|
212
288
|
}
|
|
213
289
|
```
|
|
214
290
|
|
|
291
|
+
> **Note:** _If your custom hook does not accept any parameter, you can provide `void` to the 1st generic type._
|
|
292
|
+
>
|
|
293
|
+
> e.g: `use: ({ deps: [userService] }: HookWithDeps<void, [UserService]>)`
|
|
294
|
+
|
|
215
295
|
## Examples
|
|
216
296
|
|
|
217
297
|
### Composable components
|
|
@@ -249,8 +329,8 @@ export class InputboxService {
|
|
|
249
329
|
}
|
|
250
330
|
}
|
|
251
331
|
|
|
252
|
-
export const
|
|
253
|
-
|
|
332
|
+
export const InputboxModuleBp = ProviderModule.blueprint({
|
|
333
|
+
id: 'ComponentInputboxModule',
|
|
254
334
|
provides: [InputboxService],
|
|
255
335
|
exports: [InputboxService],
|
|
256
336
|
});
|
|
@@ -263,7 +343,7 @@ export interface InputboxProps {
|
|
|
263
343
|
initialValue: string;
|
|
264
344
|
}
|
|
265
345
|
|
|
266
|
-
export const Inputbox = provideModuleToComponent<InputboxProps>(
|
|
346
|
+
export const Inputbox = provideModuleToComponent<InputboxProps>(InputboxModuleBp, ({ initialValue }) => {
|
|
267
347
|
const service = useInject(InputboxService);
|
|
268
348
|
const [, setCurrentValue] = useState(initialValue);
|
|
269
349
|
service.setStateValue = setCurrentValue;
|
|
@@ -290,8 +370,8 @@ export class ListviewService {
|
|
|
290
370
|
/* Remaining fancy implementation */
|
|
291
371
|
}
|
|
292
372
|
|
|
293
|
-
export const
|
|
294
|
-
|
|
373
|
+
export const ListviewModuleBp = ProviderModule.blueprint({
|
|
374
|
+
id: 'ComponentListviewModule',
|
|
295
375
|
provides: [ListviewService],
|
|
296
376
|
exports: [ListviewService],
|
|
297
377
|
});
|
|
@@ -304,7 +384,7 @@ export interface ListviewProps {
|
|
|
304
384
|
items: any[];
|
|
305
385
|
}
|
|
306
386
|
|
|
307
|
-
export const Listview = provideModuleToComponent<ListviewProps>(
|
|
387
|
+
export const Listview = provideModuleToComponent<ListviewProps>(ListviewModuleBp, ({ items }) => {
|
|
308
388
|
const service = useInject(ListviewService);
|
|
309
389
|
|
|
310
390
|
/* Remaining fancy implementation */
|
|
@@ -338,15 +418,15 @@ export class DropdownService {
|
|
|
338
418
|
/* Remaining fancy implementation */
|
|
339
419
|
}
|
|
340
420
|
|
|
341
|
-
export const
|
|
342
|
-
|
|
421
|
+
export const DropdownModuleBp = ProviderModule.blueprint({
|
|
422
|
+
id: 'ComponentDropdownModule',
|
|
343
423
|
// It is very important that we import all the exportable dependencies from the `ListviewModule`!
|
|
344
|
-
imports: [
|
|
424
|
+
imports: [ListviewModuleBp],
|
|
345
425
|
provides: [DropdownService],
|
|
346
426
|
exports: [
|
|
347
427
|
// Let's also re-export the dependencies of the `ListviewModule` so once we import the `DropdownModule`
|
|
348
428
|
// somewhere elese, we get access to the `ListviewModule` exported dependencies as well!
|
|
349
|
-
|
|
429
|
+
ListviewModuleBp,
|
|
350
430
|
// Let's not forget to also export our `DropdownService` :)
|
|
351
431
|
DropdownService,
|
|
352
432
|
],
|
|
@@ -363,7 +443,7 @@ export interface DropdownProps {
|
|
|
363
443
|
}
|
|
364
444
|
|
|
365
445
|
export const Dropdown = provideModuleToComponent<DropdownProps>(
|
|
366
|
-
|
|
446
|
+
ListviewModuleBp,
|
|
367
447
|
({ listviewProps, initialSelectedValue }) => {
|
|
368
448
|
const service = useInject(DropdownService);
|
|
369
449
|
|
|
@@ -412,9 +492,9 @@ export class AutocompleteService {
|
|
|
412
492
|
/* Remaining fancy implementation */
|
|
413
493
|
}
|
|
414
494
|
|
|
415
|
-
export const
|
|
416
|
-
|
|
417
|
-
imports: [
|
|
495
|
+
export const AutocompleteModuleBp = ProviderModule.blueprint({
|
|
496
|
+
id: 'ComponentAutocompleteModule',
|
|
497
|
+
imports: [InputboxModuleBp, DropdownModuleBp],
|
|
418
498
|
provides: [AutocompleteService],
|
|
419
499
|
// If we don't plan to share the internal dependencies of the
|
|
420
500
|
// Autocomplete component, then we can omit the `exports` array declaration.
|
|
@@ -431,7 +511,7 @@ export interface AutocompleteProps {
|
|
|
431
511
|
currentText: string;
|
|
432
512
|
}
|
|
433
513
|
|
|
434
|
-
export const Autocomplete = provideModuleToComponent<AutocompleteProps>(
|
|
514
|
+
export const Autocomplete = provideModuleToComponent<AutocompleteProps>(AutocompleteModuleBp, ({ inputboxProps, dropdownProps, currentText }) => {
|
|
435
515
|
const service = useInject(AutocompleteService);
|
|
436
516
|
|
|
437
517
|
service.inputboxService.currentValue = currentText;
|
|
@@ -454,8 +534,6 @@ export const Autocomplete = provideModuleToComponent<AutocompleteProps>(Autocomp
|
|
|
454
534
|
|
|
455
535
|
This should cover the fundamentals of how you can build a scalable UI by using the `xInjection` Dependency Injection 😊
|
|
456
536
|
|
|
457
|
-
> **Note:** _Keep in mind that both library ([xInjection](https://www.npmjs.com/package/@adimm/x-injection) & [xInjection ReactJS](https://www.npmjs.com/package/@adimm/x-injection-reactjs)) are still young and being developed, therefore the internals and public API may change in the near future._
|
|
458
|
-
|
|
459
537
|
## Unit Tests
|
|
460
538
|
|
|
461
539
|
It is very easy to create mock modules so you can provide them to your components in your unit tests.
|
|
@@ -472,13 +550,14 @@ class ApiService {
|
|
|
472
550
|
private async sendToLocation(user: User, location: any): Promise<any> {}
|
|
473
551
|
}
|
|
474
552
|
|
|
475
|
-
const
|
|
476
|
-
|
|
553
|
+
const ApiModuleBp = new ProviderModule.blueprint({
|
|
554
|
+
id: 'ApiModule',
|
|
477
555
|
providers: [UserService, ApiService],
|
|
478
556
|
});
|
|
479
557
|
|
|
480
|
-
|
|
481
|
-
|
|
558
|
+
// Clone returns a `deep` clone and wraps all the `methods` to break their reference!
|
|
559
|
+
const ApiModuleBpMocked = ApiModuleBp.clone().updateDefinition({
|
|
560
|
+
id: 'ApiModuleMocked',
|
|
482
561
|
providers: [
|
|
483
562
|
{
|
|
484
563
|
provide: UserService,
|
|
@@ -495,8 +574,8 @@ const ApiModuleMocked = new ComponentProviderModule({
|
|
|
495
574
|
],
|
|
496
575
|
});
|
|
497
576
|
|
|
498
|
-
// Now all the dependencies used inside the
|
|
499
|
-
await act(async () => render(<RealComponent module={
|
|
577
|
+
// Now all the dependencies used inside the "RealComponent" will be automatically resolved from the `ApiModuleBpMocked` module.
|
|
578
|
+
await act(async () => render(<RealComponent module={ApiModuleBpMocked} />));
|
|
500
579
|
```
|
|
501
580
|
|
|
502
581
|
## Documentation
|
|
@@ -511,6 +590,12 @@ Pull requests are warmly welcomed! 😃
|
|
|
511
590
|
|
|
512
591
|
Please ensure your contributions adhere to the project's code style. See the repository for more details.
|
|
513
592
|
|
|
593
|
+
## Credits
|
|
594
|
+
|
|
595
|
+
- [Adi-Marian Mutu](https://www.linkedin.com/in/mutu-adi-marian/) - Author of `xInjection` & `xInjection ReactJS`
|
|
596
|
+
|
|
514
597
|
---
|
|
515
598
|
|
|
516
|
-
>
|
|
599
|
+
> [!NOTE]
|
|
600
|
+
>
|
|
601
|
+
> **For questions, feature requests, or bug reports, feel free to open an [issue](https://github.com/AdiMarianMutu/x-injection-react/issues) on GitHub.**
|