0.1.3 • Published 1 year ago

@moln/react-ioc v0.1.3

Weekly downloads
-
License
MIT
Repository
github
Last release
1 year ago

React IoC helper

Build Status Coverage Status GitHub license npm

Use any ioc library (tsyringe, inversify, @Moln/react-ioc, etc.) in react.

Installation

Install by npm

npm install --save @moln/react-ioc

or install with yarn (this project is developed using yarn)

yarn add @moln/react-ioc

API

DependencyContainerContext & DependencyContainerProvider

Use @moln/dependency-container

class Foo { name = 'foo' }
class Bar { name = 'bar' }

const container = new DependencyContainer();
container.registerSingleton(Foo);
container.registerSingleton('MyBar', Bar);

render(
  <DependencyContainerProvider container={container}>
    <App />
  </DependencyContainerProvider>,
  document.createElement('app')
);

Use tsyringe

import {container, injectable} from "tsyringe";

// For implement `ContainerInterface`
container.get = container.resolve;

@injectable()
class Foo { name = 'foo' }

@injectable()
class Bar { name = 'bar' }

render(
  <DependencyContainerProvider container={container as ContainerInterface}>
    <App />
  </DependencyContainerProvider>,
  document.createElement('app')
);

Use inversify

import {Container, injectable} from "inversify";

const container = new Container();

@injectable()
class Foo { name = 'foo' }

@injectable()
class Bar { name = 'bar' }

render(
  <DependencyContainerProvider container={container as ContainerInterface}>
    <App />
  </DependencyContainerProvider>,
  document.createElement('app')
);

injectServices HOC

type BazProps = { foo: Foo; bar: Bar };

class BazComponent extends Component<BazProps> {
  render() {
    const {foo, bar} = this.props;
    return <div>hello {foo.name}! {bar.name}! </div>;
  }
}

const WrapperdBazComponent = injectServices({
  foo: Foo,
  bar: Bar,
})(BazComponent);

render(
  <DependencyContainerProvider container={container}>
    <WrapperdBazComponent />
  </DependencyContainerProvider>,
  document.createElement('app')
);
// By custom factory
const WrapperdBazComponent = injectServices((container, props) => {
  return {
    foo: container.get(Foo),
    bar: porps.bar || container.get(Bar),
  }
})(BazComponent);

render(
  <DependencyContainerProvider container={container}>
    <WrapperdBazComponent bar={new Bar} />
  </DependencyContainerProvider>,
  document.createElement('app')
);

useService

const BazComponent = () => {
  const foo = useService(Foo);
  const bar = useService(Bar);

  return <div>{foo.name} {bar.name}</div>;
};

render(
  <DependencyContainerProvider container={container}>
    <BazComponent />
  </DependencyContainerProvider>,
  document.createElement('app')
);

inject()

Modify your tsconfig.json to include the following settings

{
  "compilerOptions": {
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  }
}

Add a polyfill for the Reflect API (examples below use reflect-metadata). You can use:

The Reflect polyfill import should only be added once, and before DI is used:

// main.ts
import "reflect-metadata";

// Your code here...

Component usage:

class Foo { name = 'foo' }
class Bar { name = 'bar' }

// Use @moln/dependency-container demo 
const container = new DependencyContainer();
container.registerSingleton(Foo);
container.registerSingleton('MyBar', Bar);

class BazComponent extends Component {
  @inject() private foo!: Foo;
  @inject('MyBar') private bar!: Bar;
  render() {
    return <div>hello {this.foo.name}! {this.bar.name}! </div>;
  }
}