wox

An open-source library that enables dependency injection in React applications.

Getting Started

A quick tutorial to get you up and running with Wox Inject.

⚠️

Before continuing do note that Wox Inject only works with Vite (opens in a new tab) right now. We are working on adding support for other build tools.

Installation

Install the Wox Inject library using your favorite package manager.

pnpm add @wox-team/wox-inject

Usage

Once installed you can start using Wox Inject in your React application.

import { Injectable } from '@wox-team/wox-inject';
 
@Injectable()
class GreeterService {
  greet(val: string) {
    console.log(val);
  }
}
 
function App() {
  const greeterService = useResolve(GreeterService);
 
  return (
    <button type="button" onClick={() => greeterService.greet('hello!')}>click me</button>
  );
}

The basic example above isn't very useful, but it demonstrates how to use Wox Inject in your application in a foundational way.

Let's jump into some more advanced topics and why you're using this!

Decorators

In Wox Inject the @Injectable decorator is used to define a class as a dependency to be resolved. The useResolve hook is used to resolve the service in a component.

@Injectable()
class GreeterService {
  greet(val: string) {
    console.log(val);
  }
}
 
@Injectable()
class Controller {
  constructor(private greeterService: GreeterService) {}
 
  sayHello() {
    this.greeterService.greet('hello!');
  }
}

Reflection

At this step, trying to resolve Controller will result in an error.

const controller = useResolve(Controller);
controller.sayHello() // TypeError: undefined is not an object (evaluating 'this.greeterService.greet')

This is because no code reflection has been done yet. What is code reflection?

Code reflection allows a program to examine and modify its own structure at runtime. TypeScript lacks built-in reflection, so developers often use reflect-metadata to attach and inspect metadata on classes and methods at runtime.

While that route would work for build tools that bundle the code through TypeScript, it'll not work for build tools that strips out type annontations like Vite.

To fix this, you'll need to add the @wox-team/wox-inject-vite plugin to your Vite configuration. It'll not work like traditional reflection that operates at runtime, but the plugin will generate metadata at build time.

To install the plugin, use your favorite package manager.

pnpm add @wox-team/wox-inject-vite -D

Once installed, add the plugin to your Vite configuration.

import { defineConfig } from 'vite';
import { dependencyInjection } from '@wox-team/wox-inject-vite';
 
export default defineConfig({
  // ...
  plugins: [
    // ...
    dependencyInjection(),
  ],
});

You will also need to add the decorators-legacy plugin to the Babel configuration in the react plugin.

// ...
plugins: [
  react({
    babel: {
      parserOpts: {
        plugins: ['decorators-legacy'],
      },
    },
  }),
  dependencyInjection(),
],
// ...

Now you can run your application and the dependency injection will work as expected.

const controller = useResolve(Controller);
controller.sayHello() // hello!

Happy building!

Read more about Wox Inject



illustration

FAQ

The FAQ is a collection of useful questions and answers about the library. If you have a question that isn't answered here, please open an issue.

Is Wox Inject a state managment package?

No, Wox Inject have more in common with React's Context API than with state management libraries. Wox Inject allows a composition of logic to be shared across components.

You can read more about this in the Reactivity section.

Can I use Wox Inject without TypeScript

While it's technically possible to use Wox Inject without TypeScript. It's not at all recommended. Wox Inject is designed to work with TypeScript and you'll have a much better experience using it with TypeScript.

Can I use Wox Inject with Next.js?

No, not right now. Wox Inject is designed to work with React but currently we only support Vite as a build tool.