reactjs - Kan inte få egenskapen beroendeinjektion att fungera i React-projekt
Jag behöver riktigt grundläggande beroendeinjektion för ett React-projekt på ett liknande syntaktiskt sätt som i C# eller Java. Att använda context eller injektion genom props är inte ett alternativ. Jag har försökt tre lösningar hittills:
- Inversify
- Inversify-React-Decorators
- React.DI
Men ingen av dessa lösningar fungerade, vilket väckte frågan om det finns någon slags konfigurationsproblem.
Använder Inversify/Inversify-React-Decorators/Rect.DI
SomeService.ts
import { inject, injectable } from "inversify";
import { TYPES, ITokenProvider, IFileService } from "../injectables";
import { lazyInject, DIContainer } from "../inversify.config";
export class SomeService {
@inject(TYPES.ITokenProvider) private tokenProvider!: ITokenProvider; //Inversify
//@lazyInject(TYPES.ITokenProvider) private tokenProvider!: ITokenProvider;//Inversify-r-d
//@Inject tokenProvider!: TokenProvider; //react-di
(...)
}
inversify.config.ts
import "reflect-metadata";
import { Container } from "inversify";
import getDecorators from "inversify-inject-decorators";
import { TYPES, ITokenProvider, } from "./injectables";
import { TokenProvider } from "./Services/TokenProvider"
const DIContainer = new Container();
DIContainer.bind<ITokenProvider>(TYPES.ITokenProvider).toConstructor(TokenProvider);
const { lazyInject } = getDecorators(DIContainer, false);
export { DIContainer, lazyInject }
injectables.ts
export interface ITokenProvider {
getSomeToken(): Promise<string>
}
TokenProvider.ts
import "reflect-metadata";
import * as microsoftTeams from "@microsoft/teams-js";
import { injectable } from "inversify";
import { ITokenProvider } from '../injectables';
@injectable()
export class TokenProvider implements ITokenProvider {
public constructor() { }
public async getSomeToken(): Promise<string> {
(...)
}
}
App.tsx (används av react-di istället för inversify.config)
@Module({
providers: [
{ provide: AccessTokenProvider, useClass: AccessTokenProvider },
]
})
Fel
React-DI och Inversify kommer inte att lösa beroendet, vilket orsakar ett undefined-fel för egenskapen. Inversify-dekoratorer orsakar följande fel:
TokenProvider.ts:8 Uncaught ReferenceError: Cannot access 'SomeService' before initialization
at Module.SomeService (VM8 main.chunk.js:248)
at Module../src/inversify.config.ts (inversify.config.ts:11)
(...)
Konfiguration
tsconfig.json
{
"include": [
"src/*"
],
"compilerOptions": {
"target": "es5",
"jsx": "react",
"allowSyntheticDefaultImports": true,
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"types": [ "reflect-metadata" ]
}
}
Jag försökte också flytta "reflect-metadata" runt olika klasser.
Svar #1
Nested @lazyInject fungerar inte: https://github.com/inversify/InversifyJS/issues/941
Problemet existerar på grund av ett cirkulärt beroende mellan en klass (i fallet ovan, Header-klassen) och inversify.config'. inversify.config behöver importera Header för att skapa bindningarna men Header behöver åtkomst till lazy Inject som skapas i inversify.config.
Lösningen är att dela upp din befintliga inversify.config i tre filer.
Gör ingenting förutom att skapa containern (i mitt fall kallas den container.ts). Importerar containern från den föregående filen och lägger till bindningarna (i mitt fall kallade inversify.config.ts). Importerar fil 1 (inte 2!), anropar getDecorators() och exporterar lazyInject. Din klass skulle då importera lazyInject från den tredje filen istället för inversify.config.