inversify / InversifyJS

A powerful and lightweight inversion of control container for JavaScript & Node.js apps powered by TypeScript.
http://inversify.io/
MIT License
11.14k stars 712 forks source link

[React] inject is not defined #1208

Open kegi opened 4 years ago

kegi commented 4 years ago

I'm trying to use constructor injection with React. I'm using "customize-cra" and "react-app-rewire" to add babel plugins.

I added "@babel/plugin-proposal-decorators" in legacy mode and "babel-plugin-parameter-decorator".

config-override.js :

const { override, addDecoratorsLegacy, addBabelPlugins } = require('customize-cra')

module.exports = override(
    addDecoratorsLegacy(),
    addBabelPlugins(
        'babel-plugin-parameter-decorator',
    ),
)

tsconfig.json

{
  "compilerOptions": {
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext",
      "es6"
    ],
    "typeRoots": [
      "node_modules/@types"
    ],
    "allowJs": true,
    "allowSyntheticDefaultImports": true,
    "emitDecoratorMetadata": true,
    "esModuleInterop": true,
    "experimentalDecorators": true,
    "forceConsistentCasingInFileNames": true,
    "isolatedModules": true,
    "jsx": "react",
    "module": "esnext",
    "moduleResolution": "node",
    "noEmit": true,
    "removeComments": true,
    "resolveJsonModule": true,
    "sourceMap": true,
    "skipLibCheck": true,
    "strict": true
  },
  "include": [
    "src"
  ]
}

Expected Behavior

Inversify should work in both DEV and PROD builds of React

Current Behavior

There is no error while building the production build but the app won't run and throw this on the browser console :

ReferenceError: inject is not defined

Note : This is working perfectly on DEV build.

Observations

Steps to Reproduce

import { injectable, inject } from 'inversify'

@injectable()
export default class MyClass {

    constructor(
        @inject('myDependency') private myDependency: MyDependencyInterface,
    ) {
    }
}

More information

Environment

OS : Windows 10 using WSL (Ubuntu 18.04) inversify : 5.0.1 reflect-metadata : 0.1.13 @babel/plugin-proposal-decorators : 7.8.3 babel-plugin-parameter-decorator : 1.0.15 react : 16.13.1 customize-cra : 0.9.1 react-app-rewired : 2.1.5 typeScript : 3.8.3 node : 13.12.0 yarn : 1.9.4

cesalberca commented 4 years ago

Something similar is happening to me too, although can't get past an error. How did you at least make it work for development @kegi ?

kegi commented 4 years ago

Something similar is happening to me too, although can't get past an error. How did you at least make it work for development @kegi ?

To make it work, I had to rewire react and add 2 babels plugins. I documented the steps here : https://github.com/inversify/InversifyJS/issues/1004#issuecomment-598776777

khomyakov42 commented 4 years ago

I have same problem. Inversify work in dev mode, but not work in next build, only if inject using as constructor parameter decorator.

khomyakov42 commented 4 years ago

My solution for solve this problem .babelrc { "presets": [ [ "next/babel", { "class-properties": { "loose": true } } ] ], "plugins": [ "babel-plugin-transform-typescript-metadata", [ "@babel/plugin-proposal-decorators", { "legacy": true } ] ] } .tsconfig { "compilerOptions": { "baseUrl": ".", "module": "esnext", "esModuleInterop": true, "moduleResolution": "node", "target": "es2018", "downlevelIteration": true, "experimentalDecorators": true, "emitDecoratorMetadata": true, "types": ["reflect-metadata"], "jsx": "preserve", "sourceMap": true, "skipLibCheck": true, "lib": [ "dom", "dom.iterable", "esnext" ], "allowJs": true, "strict": false, "forceConsistentCasingInFileNames": true, "noEmit": true, "resolveJsonModule": true, "isolatedModules": true, "paths": { "~/*": [ "src/*" ] } }, "include": [ "src/**/*" ], "exclude": [ "node_modules" ] }

mohsinamjad commented 3 years ago

it's happening for me as well, I have added two plugins in babel config

{
  "presets": [
    "@nrwl/web/babel",
    "@nrwl/react/babel"
  ],
  "plugins": [
    "babel-plugin-transform-typescript-metadata",
    "@babel/plugin-transform-block-scoping"
  ],
  "babelrcRoots": [
    "*"
  ]
}

now it's working but i don't know if it's the right solution

da1z commented 3 years ago

still having this issue. what is the right solution here? do i need to eject CRA for solutions above?

kegi commented 3 years ago

After using another library and facing the same issues, I went to the conclusion that on prod, since the code is uglified, Inversify have a hard time linking dependencies (my guess).

Usually, all other methods works (decorator, using a single object in the constructor holding the other dependencies, etc).

@da1z even if you eject, you will only be able to make it work on dev.

kishanio commented 2 years ago

i'm having same troubles in production and on dev things seems to work fine out of box

soekasir commented 1 year ago

solved with:


const createActivityStoreClass=(activityService: ActivityService)=>{

  @injectable()
  class ActivityStore{
    public all?:ActivityDto[];
    private activityService=activityService //from function argument

    constructor(){
      makeObservable(this,{
        all: observable,
        delete: action,
        load: action,
        create: action,
      })
      this.load();
    }

    load(){
      this.activityService.getAll().then((data)=>{
        this.all=data;
      })
    }

    async create(data:CreateActivity){
      return await this.activityService.create(data).then((res)=>{
        this.all?.unshift(res)
        return res;
      });
    }

    async delete(id:number){
      return await this.activityService.delete(id).then((res)=>{
        this.all = this.all?.filter((item) => item.id !== id);
        return res
      });
    }
  }

  return ActivityStore
}

export default class ActivityStore extends createActivityStoreClass(new ActivityService()){}