npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

react-hot-wire

v0.4.1

Published

Dependency Injection in React with hot-wire

Downloads

25

Readme

react-hot-wire

npm version npm downloads GitHub issues GitHub PRs ISC license

motivation

I needed a React tool that would allow me to separate the view layer with other application layers. I wanted to be able to create services that are completely separated, that know nothing about the view. When I succeeded, there was a problem with injecting these services into individual components (at any application level). For this purpose a react-hot-wire was created. It allows to define what services a given component needs, and enables convenient injection. Additionally, the component can react to changes in services by plugging its own listener into the service cycle.

installation

main package (to integrate with React)

$ npm install --save react-hot-wire

main dependency (to resolve DI container)

$ npm install --save hot-wire

simple usage

First we should define the service(s) to be solved by the hot-wire module.

Example service:

// services/language.service.js

export default class LanguageService {
    _currentLanguage = 'en';

    currentLanguage() {
        return this._currentLanguage;
    }
}

Then by using hot-wire we create the instances of the services and inject dependencies into the appropriate places (I suggest you see the hot-wire tests). Then we pass the solved services to Provider:

// index.js

import ReactDOM from 'react-dom';
import HotWire from 'hot-wire';
import { Provider } from 'react-hot-wire';
import LanguageService from 'services/language.service';

const container = new HotWire().wire({
    services: {
        // this is example usage, we can store definitions whenever we want
        languageService: {
            class: LanguageService,
            public: true,
        },
        // other definitions of services here...
    },
});

container.then(services => {
    ReactDOM.render(
        <Provider services={services}>{/* application code here */}</Provider>,
        document.getElementById('app')
    );
});

Now you would like to inject into a component, at any level, an instance of a selected service. With help comes the wire function, which in arguments accepts the component that is to have the service injected, and the array of services to be set in props:

// components/language.component.js

import React from 'react';
import { wire } from 'react-hot-wire';

function Language({ languageService }) {
    return languageService.currentLanguage();
}

export default wire(['languageService'], Language);

or simply:

import React from 'react';
import { Wire } from 'react-hot-wire';

import Language from 'components/language.component';

export function App() {
    return (
        <Wire
            services={['languageService']}
            render={({ languageService }) => <Language lang={languageService.currentLanguage()} />}
        />
    );
}

Now we have injected the selected service into the component, and we can take full advantage of its capabilities. As the service was injected by props, we have the possibility of convenient component testing, substitution of this service, etc.

advanced usage

listening to changes

// hoc/language.hoc.js

import React, { useEffect } from 'react';
import { wire } from 'react-hot-wire';

export default Component =>
    wire(['languageService'], function LanguageHOC({ languageService, ...props }) {
        useEffect(() => {
            return languageService.addChangeListener(() => {} /* do something... */);
        });

        return <Component lang={languageService.currentLanguage()} {...props} />;
    });
// components/language.component.js

import LanguageHOC from 'hoc/language.hoc';

export function Language({ lang }) {
    return lang;
}

export default LanguageHOC(Language);
  • and small modification in the example service (extends for a Service)
- export default class LanguageService {

+ import { Service } from 'react-hot-wire';
+
+ export default class LanguageService extends Service {

API interface

<Provider>

  • property services: Object<string, Object> - services after a resolved container

<Wire>

  • property services: string[]

  • property render: (services: Object<string, Object>): Component

wire()

  • wire(Component: Component, dependencies: string[]): Component

class Service

  • addChangeListener(changeListener: Function): Function

  • runChangeListeners(): void