An open API service indexing awesome lists of open source software.

https://github.com/igoodie/react-compound-composer

🖇️ Spend less time crafting your complex Compound Components
https://github.com/igoodie/react-compound-composer

complex component compound library nested react

Last synced: 7 months ago
JSON representation

🖇️ Spend less time crafting your complex Compound Components

Awesome Lists containing this project

README

          


Logo


Spend less time crafting your Compound Components structure































# Description

This library aims to make it easier to develop and maintain **Compound Components** by encapsulating **context creation** and **compound composition** logic under two core helpers.

Check those amazing posts to learn more about Compound Components:

- https://www.smashingmagazine.com/2021/08/compound-components-react/
- https://betterprogramming.pub/compound-component-design-pattern-in-react-34b50e32dea0
- https://blog.logrocket.com/understanding-react-compound-components/

# Examples/Demo

- [Stackblitz Collection](https://stackblitz.com/@iGoodie/collections/react-compound-composer)

1. [Simple Counter Example](https://stackblitz.com/edit/stackblitz-starters-e639ls?file=src%2FCounter.component.tsx): An almost in-line example of a Counter with its own state. Here just for a very quick proof-of-concept.
2. [A Better Structured Example](https://stackblitz.com/edit/stackblitz-starters-ltkqyc?file=src%2Fcomponents%2Faccordion%2Faccordion.tsx): An example of an Accordion compound
3. [Nested Compounds Example](https://stackblitz.com/edit/stackblitz-starters-aexdiu?file=src%2Fcomponents%2Faccordion%2Fbody%2Faccordion-body.tsx): An example of nested compound
4. [Flattened Root Example](https://stackblitz.com/edit/stackblitz-starters-yhr2uv?file=src%2FApp.tsx): An example of how you can flatten `Root` components

# How to Use?

## 1. Create your Context

Start off by creating your context. This context will be available via a hook on all the sub-components. A good way to keep a dispatch-editable state across the components.

```tsx
import { contextBuilder } from "react-compound-composer";

interface CounterRootProps extends React.PropsWithChildren {
initialCount?: number;
}

const {
Consumer: CounterConsumer, // Consumer is also returned, just for convenience
Provider: CounterProvider,
useContext: useCounterContext,
} = contextBuilder((rootProps: CounterRootProps) => {
const [count, setCount] = useState(rootProps.initialCount ?? 0);

return {
count,
increase: (count: number) => setCount((c) => c + count),
decrease: (count: number) => setCount((c) => c - count),
};
});
```

## 2. Create your Root & Sub Components

Create a few components to be composed under the compound.

```tsx
import React from "react";

const CounterRoot = (props: CounterRootProps) => {
return (


{props.children}

);
};
```

```tsx
import React from "react";

const CounterCount = () => {
const ctx = useCounterContext();
return {ctx.count};
};
```

```tsx
import React from "react";

const CounterIncrease = () => {
const ctx = useCounterContext();
return ctx.increase(1)}>Increase;
};
```

```tsx
import React from "react";

const CounterDecrease = () => {
const ctx = useCounterContext();
return ctx.decrease(1)}>Decrease;
};
```

## 3. Compose your Compound with them!

Finally compose your Compound with the components you've created.

```tsx
import { compoundBuilder } from "react-compound-composer";

export const Counter = compoundBuilder({
name: "Counter",
provider: CounterProvider,
components: {
Root: CounterRoot,
Count: CounterCount,
Increase: CounterIncrease,
Decrease: CounterDecrease,
},
});
```

## 4. Enjoy your Compound!

Use your compound as desired.

```tsx
export default function App() {
return (







);
}
```

## How to Flatten `Root` Components?

If you prefer using the root components without actually using their `Root` properties, you can set the `flattenRoot` option to `true`. Like so:

```tsx
import { compoundBuilder } from "react-compound-composer";

export const Counter = compoundBuilder({
name: "Counter",
provider: CounterProvider,
flattenRoot: true,
components: {
Root: CounterRoot,
Count: CounterCount,
Increase: CounterIncrease,
Decrease: CounterDecrease,
},
});
```

and use the Compound like so:

```tsx
export default function App() {
return (







);
}
```

## License

© 2023 Taha Anılcan Metinyurt (iGoodie)

For any part of this work for which the license is applicable, this work is licensed under the [Attribution-ShareAlike 4.0 International](http://creativecommons.org/licenses/by-sa/4.0/) license. (See LICENSE).

Creative Commons License