Open Laazarus opened 5 years ago
Same problem. Any idea?
@weilao I tried everything I could and I found on the internet but I could not make it working...
I ended up using another library for now that used inversifyjs behind the scene but i really would like to use this method because it feels like more official...
I did not have any luck so far though.
Let me know if you want to know the library I am using (that one works)but as said i really would prefer using this the method describe here
Also if you find the solution I would really appreciate if you could share it :)
Regards
As far as I know, it's caused by @babel/plugin-proposal-class-properties
.
The code above was compiled to something like:
class Game extends React.Component {
constructor() {
// This is why the injection broken.
this.gameService = undefined;
}
}
Use a workaround to make the inject work.
class Game extends React.Component {
gameService: GameService = container.get(GameService);
}
Thanks, it is a shame you cannot use the normal injection :(
On 18 Jan 2019 08:03, 威老 notifications@github.com wrote:
Use a workaround to make the inject work.
class Game extends React.Component { gameService: GameService = container.get(GameService); }
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHubhttps://github.com/inversify/InversifyJS/issues/1026#issuecomment-455459648, or mute the threadhttps://github.com/notifications/unsubscribe-auth/AFdH2qkauahQCj1B-BLBuHAzVGvOCgZiks5vEX--gaJpZM4ZnAFa.
In this week I started to learn about inversify with React too and I'm having the same issue... I got the basic example of https://github.com/inversify/inversify-inject-decorators and just pasted it on a new class in my project, just to test, and even the basic example was not working.
I was looking in the implementation, trying to find some guess of what was happening... This library (if I didnt get wrong) inject the properties on the prototype of the object, so the injection works only when you do a get on the property of prototype.
When you do a get on the object, the js will look at the instance to see if the property exists there. If it doesnt then Js will look at the instance's prototype chain until get the value wanted.
The problem is that when you create a instance (new WhateverClass()) all properties will be in your instance, so js will never do a search on the prototype chain and, because of that, your instance will never be injected.
To exemplify what I'm talking about I got the basic example I said above and made some changes. That's an example of what is happening here:
@dcavanagh and @remojansen, Do you have some guess about what is happening here?
import "reflect-metadata"
import getDecorators from "inversify-inject-decorators";
import { Container, injectable, tagged, named } from "inversify";
let container = new Container();
let { lazyInject } = getDecorators(container);
let TYPES = { Weapon: "Weapon" };
interface Weapon {
name: string;
durability: number;
use(): void;
}
@injectable()
class Sword implements Weapon {
public name: string;
public durability: number;
public constructor() {
this.durability = 100;
this.name = "Sword";
}
public use() {
this.durability = this.durability - 10;
}
}
class Warrior {
constructor(){}
@lazyInject(TYPES.Weapon)
weapon: Weapon;
}
container.bind<Weapon>(TYPES.Weapon).to(Sword);
let warrior = new Warrior();
console.log(warrior.weapon instanceof Sword); // false
delete warrior.weapon
console.log(warrior.weapon instanceof Sword); // true
export default warrior```
Any updates on this?
Seems related to #1050.
EDIT: Oh, I did not see you were the author of the related issue ^^
Just found this issue while trying to solve the same problem for project using babel with plugin-proposal-decorators (legacy mode).
My workaround is to define own decorators which exploit babel's internal initializer
(can read about it here) descriptor property to settle down prototype lookup:
const DECORATORS = getDecorators(myContainer);
interface IBabelPropertyDescriptor extends PropertyDescriptor {
initializer(): any;
}
export const injectProperty = function(serviceIdentifier: interfaces.ServiceIdentifier<any>) {
const original = DECORATORS.lazyInject(serviceIdentifier);
// the 'descriptor' parameter is actually always defined for class fields for Babel, but is considered undefined for TSC
// so we just hack it with ?/! combination to avoid "TS1240: Unable to resolve signature of property decorator when called as an expression"
return function(this: any, proto: any, key: string, descriptor?: IBabelPropertyDescriptor): void {
// make it work as usual
original.call(this, proto, key);
// return link to proto, so own value wont be 'undefined' after component's creation
descriptor!.initializer = function() {
return proto[key];
};
};
};
// same overrides go for other 3 lazy* decorators
Usage:
export class MyClassWithInjection extends React.Component<IMyProps, IMyState> {
// here we recieve TS1240 error, if didn't use ?/! hack
@injectProperty(foo) private _foo!: IFoo;
//...
private _invokeSomethingOnFoo = () => {
this._foo.bar();
};
}
Any update on this?
Any update on this? Workarounds actually not working for us...
Any update on this?
Any update on this?
Any update on this?
Hello, we are currently in a major refactoring. I am sorry we don't have time for all the issues, We will try to focus on making v6 stable ( focus on making typescript compiler more strict, add "proper" typings, refaactor a lot of the code, fix multiple issues. ... ). We will focus on issues after that is at least green. ( we have issues that are so old ( 2018 ) that they are probably not even replicable anymore ).
Any help is much appreciated.
Any update on this??
no updates, but feel free to try a PR for this
I also have same issue, solved with:
const createActivityStoreClass=(activityService: ActivityService)=>{
@injectable()
class ActivityStore{
public all?:ActivityDto[];
public activityService=activityService
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()){}
I am writing learning React and I wanted to use it inversifyjs as I have been using it for other projects. I have seen that in order to use it with react we have to use inversify-inject-decorators and I have followed the guide for this package but I cannot get the injection working
Expected Behavior
IoC.ts
in GameServices
Game Component
This code should work
Current Behavior
I am not getting any compilation error but when the line
gets executed I get an exception because gameService is undefined..
Environment