Skip to content

fullstackhouse/react-compose

Repository files navigation

@fullstackhouse/react-compose

Compose React providers and components to avoid deeply nested JSX trees.

The Problem

// Provider hell - deeply nested JSX
function App() {
  return (
    <ThemeProvider>
      <AuthProvider>
        <I18nProvider>
          <RouterProvider>
            <QueryProvider>
              <AppContent />
            </QueryProvider>
          </RouterProvider>
        </I18nProvider>
      </AuthProvider>
    </ThemeProvider>
  );
}

The Solution

import { compose } from "@fullstackhouse/react-compose";

const App = compose([
  ThemeProvider,
  AuthProvider,
  I18nProvider,
  RouterProvider,
  QueryProvider,
  AppContent,
]);

Installation

npm install @fullstackhouse/react-compose

Usage

Basic Composition

import { compose } from "@fullstackhouse/react-compose";

const MyScreen = compose([
  AuthProvider,
  ThemeProvider,
  MyScreenContent,
]);

// Use it like a normal component
<MyScreen />;

Passing Props to Providers

Use tuple syntax [Component, props] to pass props to specific providers:

const MyScreen = compose([
  [ThemeProvider, { theme: "dark" }],
  [I18nProvider, { locale: "en" }],
  MyScreenContent,
]);

Props Flow to Content Component

Props passed to the composed component are forwarded to the innermost component:

interface ContentProps {
  userId: string;
}

function UserProfile({ userId }: ContentProps) {
  return <div>User: {userId}</div>;
}

const Screen = compose<ContentProps>([
  AuthProvider,
  UserProfile,
]);

// Props are passed to UserProfile
<Screen userId="123" />;

Mixing Tuple and Non-Tuple Providers

const MyScreen = compose([
  AuthProvider, // No props needed
  [ThemeProvider, { theme: "dark" }], // With props
  [QueryProvider, { staleTime: 5000 }], // With props
  DataProvider, // No props needed
  MyScreenContent,
]);

API

compose(providers)

Composes an array of React components/providers into a single component.

Parameters:

  • providers - Array of components or [component, props] tuples

Returns:

  • A React component that renders all providers nested in order

Type Parameters:

  • TProps - Props type for the composed component (optional, defaults to object)

Provider<TProps>

Type for a provider in the composition array:

type Provider<TProps> =
  | ComponentType<PropsWithChildren<TProps>>
  | readonly [ComponentType<PropsWithChildren<TProps>>, TProps];

How It Works

Components are nested in order, with the first being the outermost wrapper:

compose([A, B, C])
// Renders as:
<A>
  <B>
    <C />
  </B>
</A>

License

MIT

About

Compose React providers and components to avoid deeply nested JSX trees

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •