InversifyJS
InversifyJS copied to clipboard
[React] inject is not defined
I'm trying to use constructor injection with React. I'm using "customize-cra" and "react-app-rewire" to add babel plugins.
- https://github.com/arackaf/customize-cra
- https://github.com/timarney/react-app-rewired
I added "@babel/plugin-proposal-decorators" in legacy mode and "babel-plugin-parameter-decorator".
- https://www.npmjs.com/package/@babel/plugin-proposal-decorators
- https://www.npmjs.com/package/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
- the "inject" reference in the error is the Inversify annotation call (the one I'm using on my class constructor). I created a global function "inject" and was able to see all my dependencies sent as argument.
- On the build, I see
T=inject("myDependency")
- I have the feeling that Inversify inject annotation is just not included on my production build.
Steps to Reproduce
import { injectable, inject } from 'inversify'
@injectable()
export default class MyClass {
constructor(
@inject('myDependency') private myDependency: MyDependencyInterface,
) {
}
}
More information
- I'm importing "reflect-metadata" on my very first line of code.
- I'm only using constructor injection.
- I'm using typescript and yarn
- I'm not injecting dependencies on react components
- I have a NodeJS project with almost the same configuration and I can use constructor injection without problem. I think that might be related to my tsconfig (which is slightly different)
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
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 ?
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
I have same problem. Inversify work in dev mode, but not work in next build, only if inject using as constructor parameter decorator.
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" ] }
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
still having this issue. what is the right solution here? do i need to eject CRA for solutions above?
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.
i'm having same troubles in production and on dev things seems to work fine out of box
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()){}