loading...

Say Goodbye To Provider Hell With react-component-pack

horusgoul profile image Horus Lugo ・1 min read

If you're developing apps with React, you may have faced something like this:

function App() {
  return (
    <AuthProvider>
      <DataProvider>
        <AnotherDataProvider>
          <WtfProvider>
            <ThisIsGettingReallyBigProvider>
              <OhMyGodTheresMoreProvider>
                <FinallySomeRealComponents />
              </OhMyGodTheresMoreProvider>
            </ThisIsGettingReallyBigProvider>
          </WtfProvider>
        </AnotherDataProvider>
      </DataProvider>
    </AuthProvider>
  );
}

That's what people call Provider Hell and I created this tool to make this kind of code more readable.

Here's the same example, using the react-component-pack utility:

import { createPack } from 'react-component-pack';

const ProviderPack = createPack(
  AuthProvider,
  DataProvider,
  AnotherDataProvider,
  WtfProvider,
  ThisIsGettingReallyBigProvider,
  OhMyGodTheresMoreProvider
);

function App() {
  return (
    <ProviderPack>
      <FinallySomeRealComponents />
    </ProviderPack>
  );
}

NOTE: This utility won't allow you to pass props to a specific provider. Feel free to submit a PR 😁

React Component Pack · npm version license

Say goodbye to provider hell with react-component-pack, a utility that allows you to group multiple components into a single one

npm install react-component-pack

Usage

With react-component-pack you can go from this:

function App() {
  return (
    <AuthProvider>
      <DataProvider>
        <AnotherDataProvider>
          <WtfProvider>
            <ThisIsGettingReallyBigProvider>
              <OhMyGodTheresMoreProvider>
                <FinallySomeRealComponents />
              </OhMyGodTheresMoreProvider>
            </ThisIsGettingReallyBigProvider>
          </WtfProvider>
        </AnotherDataProvider>
      </DataProvider>
    </AuthProvider>
  );
}

To this:

import { createPack } from 'react-component-pack';

const ProviderPack = createPack(
  AuthProvider,
  DataProvider,
  AnotherDataProvider,
  WtfProvider,
  ThisIsGettingReallyBigProvider,
  OhMyGodTheresMoreProvider
);

function App() {
  return (
    <ProviderPack>
      <FinallySomeRealComponents />
    </ProviderPack>
  );
}

Posted on Feb 27 by:

horusgoul profile

Horus Lugo

@horusgoul

Software development has been my passion for years. I've been always building stuff with the purpose of helping others to learn, build communities or even just for fun.

Discussion

markdown guide
 

I wouldn't install a new dependency on my project to do this when you can achieve (probably) the same result just writing a small function like this one:

const nest = (...components) => props =>
  components.reduce((children, Current) => <Current {...props}>{children}</Current>, props.children);

const ProviderPack = nest(
  AuthProvider,
  DataProvider,
  AnotherDataProvider,
  WtfProvider,
  ThisIsGettingReallyBigProvider,
  OhMyGodTheresMoreProvider
);
 

How do you handle Providers which require props, e.g. Draqula requires a client (and so does Apollo and many others)? Am I supposed to do something like

const ProviderPack = createPack(
  AuthProvider,
  DataProvider,
  AnotherDataProvider,
  WtfProvider,
  ThisIsGettingReallyBigProvider,
  OhMyGodTheresMoreProvider,
  () => DraqulaProvider({ client: myClient })
);

? Not that it's too bad, now that I look at it :D

 

Almost there, remember that invoking components like that is not recommended, just change it to use JSX:

() => <DraqulaProvider client={myClient} />
 

You can create a wrapper component using the children prop containing all providers and having as props all the things you need to pass to providers.

 

I like this! I was looking for something just like it recently. I'll definitely be using this