{"id":17230084,"url":"https://github.com/robinbuschmann/react.di","last_synced_at":"2025-04-13T15:13:37.027Z","repository":{"id":38939705,"uuid":"109307395","full_name":"RobinBuschmann/react.di","owner":"RobinBuschmann","description":"Dependency injection for react based upon inversify.","archived":false,"fork":false,"pushed_at":"2022-12-07T17:32:45.000Z","size":396,"stargazers_count":98,"open_issues_count":21,"forks_count":5,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-04-13T15:13:30.936Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RobinBuschmann.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-11-02T19:06:16.000Z","updated_at":"2025-04-02T10:01:03.000Z","dependencies_parsed_at":"2023-01-24T19:32:57.552Z","dependency_job_id":null,"html_url":"https://github.com/RobinBuschmann/react.di","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobinBuschmann%2Freact.di","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobinBuschmann%2Freact.di/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobinBuschmann%2Freact.di/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobinBuschmann%2Freact.di/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RobinBuschmann","download_url":"https://codeload.github.com/RobinBuschmann/react.di/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248732488,"owners_count":21152852,"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-15T04:52:24.162Z","updated_at":"2025-04-13T15:13:36.999Z","avatar_url":"https://github.com/RobinBuschmann.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![NPM](https://img.shields.io/npm/v/react.di.svg)](https://www.npmjs.com/package/react.di)\n[![Build Status](https://travis-ci.org/RobinBuschmann/react.di.svg?branch=master)](https://travis-ci.org/RobinBuschmann/react.di)\n[![codecov](https://codecov.io/gh/RobinBuschmann/react.di/branch/master/graph/badge.svg)](https://codecov.io/gh/RobinBuschmann/react.di)\n\n# react.di\nDependency injection for react based upon [inversify](https://github.com/inversify/InversifyJS).\n\n - [Installation](#installation)\n - [Getting started](#getting-started)\n - [Injection](#injection)\n     - [Injection from class references](#injection-from-class-references)\n     - [Injection via tokens](#injection-via-tokens)\n     - [Multi injection](#multi-injection)\n     - [Inject into React Components](#inject-into-react-components)\n     - [Inject into Services](#inject-into-services)\n - [Sharing providers](#sharing-providers)\n    - [Importing modules](#importing-modules-in-other-modules)\n    - [Hierarchical shared providers](#hierarchical-shared-providers)\n - [Testing](#testing)\n - [API](#api)\n    - [Injectable](#injectable)\n    - [Inject](#inject)\n    - [Module](#module)\n    - [providers (Option)](#providers-option)\n        - [Injecting a class constructor](#injecting-a-class-constructor)\n        - [Injecting a value](#injecting-a-value)\n        - [Injection via factories](#injection-via-factories)\n    - [imports (Option)](#imports-option)\n    - [autoBindInjectable (Option)](#autobindinjectable-option)\n    - [TestBed (React Component)](#test-bed-react-component)\n    - [Provider (React Component)](#provider-react-component)\n\n## Installation\n```\nnpm install react.di@next reflect-metadata --save\n```\n\nYour `tsconfig.json` needs to be configured with  the following flags:\n```\n\"experimentalDecorators\": true,\n\"emitDecoratorMetadata\": true\n```\n\n**For version 1.0 see https://github.com/RobinBuschmann/react.di/tree/1.0**\n\n## Getting started\n#### 1. Define injectables (values/class)\n*Service*\n```typescript\nimport {Injectable, Inject} from 'react.di';\n\n@Injectable\nexport class UserService {\n  constructor(@Inject private httpClient: SomeHttpClient) {}\n\n  getUser() {}\n}\n```\n*Config*\n```typescript\nconst CONFIG_TOKEN = 'config'; // or Symbol('config');\nconst config: Config = {...};\n```\n#### 2. Inject service/value into react component\n```typescript jsx\nimport {Inject} from 'react.di';\n\nclass UserContainer extends Component\u003cany, any\u003e {\n  @Inject userService: UserService;\n  @Inject(CONFIG_TOKEN) config: Config;\n  \n  async componentDidMount() {\n    const user = await this.userService.getUser();\n    this.setState({user});\n  }\n\n  render() {\n    return (\u003cUser user={this.state.user} /\u003e); \n  }\n}\n```\n#### 3. Setup module\n```typescript jsx\nimport {Module} from 'react.di';\n\n@Module({\n  providers: [\n    {provide: UserService, useClass: UserService},\n    UserService, // or shorthand\n    {provide: CONFIG_TOKEN, useValue: config},\n    {provide: CONFIG_TOKEN, useFactory: context =\u003e config}, // or using factory\n  ]\n})\nclass App extends Component {\n  render() {\n    return (\n        \u003cPanel\u003e\n          \u003cUserContainer/\u003e\n        \u003c/Panel\u003e\n    );\n  }\n}\n```\n\n## Injection\n\n### Injection from class references\nIf you want to inject a service instance, simply mark the property with `@Inject`.\nThe type from which the instance will be created, will be derived from the\nannotated type. Notice, that the type needs to be a class. An interface won't \nwork, cause it will not exist on runtime anymore (See \n[Injection via tokens](#injection-via-tokens) to get it work with interfaces). \n```typescript\n@Inject userService: UserService;\n```\nA services class need to be annotated with `@Injectable` otherwise it will not\nbe - of course - injectable.\n\n### Injection via tokens\nDependencies can also be identified by a token. This makes sense when injecting\na value (for example a configuration) or if you want annotate these properties\nwith interfaces instead of class references.\n```typescript\n@Inject(CONFIG_TOKEN) config: Config;\n```\n\n### Multi injection\nMulti injection means that all providers for a specified identifier\nwill be injected.\nSo if the annotated type of the dependency is of type `Array`, the \ninjection will automatically processed as a multi-injection. In this \ncase the identifier needs to be passed explicitly:\n```typescript\n@Inject(INTERCEPTOR_TOKEN) interceptors: Interceptor[];\n```\n\n### Inject into React Components\nDependencies of react component need be injected via property injection:\n```typescript jsx\nimport {Inject} from 'react.di';\n\nclass UserComponent extends Component\u003cany, any\u003e {\n  @Inject userService: UserService;\n  @Inject(OtherService) otherService: OtherService;\n  @Inject(CONFIG_TOKEN) config: Config;\n  @Inject(TRANSLATION_TOKEN) translations: Translation[];\n  \n  ...\n}\n```\n\n### Inject into Services\nDependencies of services will be injected via constructor injection:\n```typescript\nimport {Injectable, Inject} from 'react.di';\n\n@Injectable\nexport class UserService {\n  constructor(@Inject http: HttpClient,\n              @Inject(OtherService) otherService: OtherService,\n              @Inject(HISTORY_TOKEN) history: IHistory) {}\n}\n```\n\n## Sharing providers\nProviders can be shared via importing from siblings or inheriting them from\nparent components.\n\n#### Importing modules in other modules\nModules can be imported in other modules to share its providers.\n```typescript jsx\n@Module({providers: [CommonService]})\nclass CommonModule extends Component {}\n\n@Module({\n  imports: [CommonModule],\n  providers: [UserService],\n})\nclass UserModule extends Component {\n  @Inject userService: UserService;\n  @Inject commonService: CommonService;\n}\n\n@Module()\nclass Root extends Component {\n  render() {\n    return (\n      \u003cUserModule/\u003e\n    );\n  }\n```\n\n#### Hierarchical shared providers\nNesting `Module` annotated components in another `Module` annotated components \nis supported.\nAll defined providers of the parent module will be inherited to its\nchild modules:\n```typescript jsx\n@Module({providers: [UserService]})\nclass UserModule extends Component {}\n\n@Module({providers: [CommonService]})\nclass App extends Component {\n  render() {\n    return (\n      \u003cUserModule/\u003e // CommonService will also be available in UserModule\n    );\n  }\n```\nProviders that are already defined in a parent, will be overridden\nif they are also defined in its child.\n\n## Testing\nFor testing purposes `react.di` provides a `TestBed` component. Nest the\ncomponents you want to test in `TestBed` and setup its dependencies in\nthe `providers` prop of `TestBed`:\n```typescript jsx\nimport {mount} from 'enzyme';\n\nmount(\n  \u003cTestBed providers={[{provide: UserService, useClass: UserServiceMock}]}\u003e\n    \u003cUserProfileContainer/\u003e\n  \u003c/TestBed\u003e\n);\n```\nor for defining a much simpler mock:\n```typescript jsx\nmount(\n  \u003cTestBed providers={[{provide: UserService, useValue: {getUser() {...}}}]}\u003e\n    \u003cUserProfileContainer/\u003e\n  \u003c/TestBed\u003e\n);\n```\n\n## API\n\n### Injectable\n`Injectable` decorator marks a class as available to the inversify `Container`.\n```typescript\nimport {Injectable} from 'react.di';\n\n@Injectable\nexport class UserService {}\n```\n\n### Inject\nThe `Inject`/`Inject(Identifier)` decorator tells the di-system what need to be injected\nand in which property the injected value should be referenced.\n\n### Module\nAll components that should be feedable with the defined providers,\nneed to be nested in a module annotated component - But don't(!) need to be\ndirect children.\n```typescript jsx\n@Module({\n  providers: [...],\n  imports: [...],\n  autoBindInjectable: true, // default is false\n})\nclass App extends Component {}\n```\n\n#### `providers` (Option)\n(optional) Array of all available providers.\n\n##### Injecting a class constructor\n```typescript\n[{provide: UserService, useClass: UserService}]\n```\n*Shorthand*\n```typescript\n[UserService]\n```\nAll instantiated dependencies will be a **singleton** by default. If you don't\nwant a dependency to be singleton set `noSingleton` to `true`:\n```typescript\n[{provide: UserService, useClass: UserService, noSingleton: true}]\n```\n\n##### Injecting a value\n```typescript\n[{provide: UserService, useValue: someUserService}]\n```\n\n##### Injection via factories\nDependencies can be injected via factories. A factory is a simple function,\nthat gets the context of the current scope and returns the value, that\nwill be injected.\n```typescript\n[{provide: UserService, useFactory: context =\u003e someValue}]\n```\n\n#### `imports` (Option)\n(optional) Array of all modules that should be imported.\n```typescript\n[CommonModule, UserModule]\n```\n\n#### `autoBindInjectable` (Option)\n(optional, default: `false`) When `autoBindInjectable` is set to `true`, injectable\nclass constructors don't need to be defined as providers anymore.\nThey will be available for injection by default. \nSo that `[{provide: UserService, useClass: UserService}]` or `[UserService]`\ncan be omitted:\n```typescript\n@Module({autoBindInjectable: true})\nclass App extends Component{}\n```\n```jsx\n\u003cTestBed autoBindInjectable={true}\u003e\n  ... // UserService will be available anyway\n\u003c/TestBed\u003e\n```\n\n#### TestBed (React Component)\n```typescript jsx\n\u003cTestBed providers={[...]} autoBindInjectable={true}\u003e\n  ...\n\u003c/TestBed\u003e\n```\n\n#### Provider (React Component)\nThe `\u003cProvider\u003e` component is a react component, that provides low-level\nsupport for inversifyJS containers. In other words: It takes an \ninversify container as property. So if you want to use all features\nof inversify, this is the component you will fall in love with:\n```typescript jsx\nconst container = new Container();\ncontainer.bind(Ninja).to(Samurai);\n\n\u003cProvider container={container}\u003e\n  ...\n\u003c/Provider\u003e\n``` \n \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobinbuschmann%2Freact.di","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frobinbuschmann%2Freact.di","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobinbuschmann%2Freact.di/lists"}