1.3.1-dev.8 • Published 7 years ago

@bem-react/di v1.3.1-dev.8

Weekly downloads
106
License
MPL-2.0
Repository
github
Last release
7 years ago

Dependency Injection (DI)

Dependency Injection (DI) allows you to split React components into separate versions and comfortably switch them in the project whenever needed, e.g., to make a specific bundle.

DI package helps to solve similar tasks with minimum effort:

  • decouple desktop and mobile versions of a component
  • implement an experimental version of a component alongside the common one

Install

npm i @bem-react/di -S

Quick start

Note! This example uses ClassName package.

E.g., for a structure like this:

Components/
  Header/
    Header@desktop.tsx
    Header@mobile.tsx
  Footer/
    Footer@desktop.tsx
    Footer@mobile.tsx
App.tsx

First, create two files that define two versions of the App and use different sets of components: App@desktop.tsx and App@mobile.tsx. Put them near App.tsx.

In each App version (App@desktop.tsx and App@mobile.tsx) we should define which components should be used. Three steps to do this: 1. Create a registry with a particular id:

const registry = new Registry({ id: cnApp() });
  1. Register all the needed components versions under a descriptive key (keys, describing similar components, should be the same across all the versions):
registry.set(cnHeader(), Header);
registry.set(cnFooter(), Footer);
  1. Export the App version with its registry of components:
export const AppNewVersion = withRegistry(registry)(AppCommon);

The files should look like this:

1. In App@desktop.tsx

import { cn } from '@bem-react/classname';
import { Registry, withRegistry } from '@bem-react/di';
import { App as AppCommon } from './App';

import { Footer } from './Components/Footer/Footer@desktop';
import { Header } from './Components/Header/Header@desktop';

const cnApp = cn('App');
const cnHeader = cn('Header');
const cnFooter = cn('Footer');

const registry = new Registry({ id: cnApp() });

registry.set(cnHeader(), Header);
registry.set(cnFooter(), Footer);

export const AppDesktop = withRegistry(registry)(AppCommon);

2. In App@mobile.tsx

import { cn } from '@bem-react/classname';
import { Registry, withRegistry } from '@bem-react/di';
import { App as AppCommon } from './App';

import { Footer } from './Components/Footer/Footer@mobile';
import { Header } from './Components/Header/Header@mobile';

const cnApp = cn('App');
const cnHeader = cn('Header');
const cnFooter = cn('Footer');

const registry = new Registry({ id: cnApp() });

registry.set(cnHeader(), Header);
registry.set(cnFooter(), Footer);

export const AppMobile = withRegistry(registry)(AppCommon);

Time to use these versions in your app dynamically!

If in App.tsx your dependencies were static before

import { cn } from '@bem-react/classname';
import { Header } from './Components/Header/Header';
import { Footer } from './Components/Footer/Footer';

const cnPage = cn('Page');

export const App: React.SFC = () => (
    <div className={ cnPage() }>
        <Header />
        <Content />
        <Footer />
    </div>
);

Now the dependencies can be injected based on the currently used registry

import { cn } from '@bem-react/classname';
import { RegistryConsumer } from '@bem-react/di';

// No Header or Footer imports

const cnApp = cn('App');
const cnPage = cn('Page');
const cnHeader = cn('Header');
const cnFooter = cn('Footer');

export const App: React.SFC = () => (
    <RegistryConsumer>
        {registries => {
            // Get registry with components
            const registry = registries[cnApp()];
            
            // Get the needed version of the component based on registry
            const Header = registry.get(cnHeader());
            const Footer = registry.get(cnFooter());

            return(
                <div className={ cnPage() }>
                    <Header />
                    <Content />
                    <Footer />
                </div>
            );
        }}
    </RegistryConsumer>
);

export default App;

So you could use different versions of your app e.g. for conditional rendering on your server side or to create separate bundles

import { AppDesktop } from './path-to/App@desktop';
import { AppMobile } from './path-to/App@mobile';
5.0.0

3 years ago

3.1.1

4 years ago

3.1.0

4 years ago

3.0.0

4 years ago

2.2.8

4 years ago

2.2.7

4 years ago

2.2.6

4 years ago

2.2.5

5 years ago

2.2.4

5 years ago

2.2.3

5 years ago

2.2.2

5 years ago

2.2.1

6 years ago

2.1.1-dev.6

6 years ago

2.2.0

6 years ago

2.1.0

6 years ago

2.0.4

6 years ago

2.0.3

6 years ago

2.0.2

6 years ago

2.0.1

6 years ago

2.0.0

6 years ago

1.6.0

6 years ago

1.5.3

6 years ago

1.5.2

6 years ago

1.5.1

6 years ago

1.5.0

7 years ago

1.4.0-dev.1

7 years ago

1.4.0

7 years ago

1.3.1-dev.8

7 years ago

1.3.1-dev.7

7 years ago

1.3.1-dev.6

7 years ago

1.3.0

7 years ago

1.2.2

7 years ago

1.2.1

7 years ago

1.2.0

7 years ago

1.1.1-dev.546

7 years ago

1.1.0

7 years ago

1.0.3

7 years ago

1.0.2

7 years ago

1.0.1

7 years ago

1.0.0

7 years ago

0.2.4

7 years ago

0.2.3

7 years ago

0.2.2

7 years ago

0.2.1

7 years ago

0.2.0

7 years ago