A tiny library of functional utilities for composing React components:
compinators = Component Combinators
.
Create three new components by partially applying the <Label>
component
color
prop, one for each member of the COLORS
union:
import {String} from 'effect'
import {unionVariants} from 'react-compinators'
const [ GreenLabel, YellowLabel, RedLabel ] = unfoldProp(
Label, // Component that we will wrap three times.
'color', // Prop that we will partially apply.
)(
COLORS, // Array of union members.
String.capitalize, // Optional function will be used to compute variant
// displayName from its `color` prop.
)
See the tutorial for more info.
> pnpm add react-compinators
You can then import any of the exported functions from the package
react-compinators
. For example to import the assume
function in your
component:
import {assume} from 'react-compinators'
React offers Far More Than One Way to compose and repurpose components. For example, you can fiddle with their props and wrap them in various ways. Whatever you do, eventually you will end up with a new component. The functions here provide a lighter alternative, via functions that React calls Higher Order Components (HOCs).
Consider a colored <Label>
component with props of type:
interface LabelProps {
text: string
color: 'red' | 'yellow' | 'green'
}
If we find ten yellow labels in our code, we could create a new
<YellowLabel>
component, where the color is fixed on yellow
:
const YellowLabel = ({text: string}) => (
<Label {...{text}} color='yellow' />
)
// Using:
<YellowLabel text='Hello World!' />
Using the assumeProp
combinator from this library, we have lighter alternative that avoids JSX:
import {assumeProp} from 'react-compinators'
import type {FC} from 'react'
// Note correct computed type for YellowLabel props.
const YellowLabel: FC<{text: string}> = assumeProp(Label, {color: 'yellow'})
// Using:
<YellowLabel text='Hello World!' />
The result is exactly the same. The style of HOCs you will find here is
supported by React Dev Tools
so the debug experience of the <YellowLabel>
should similar, except it will
appear under the name <Yellow(Label)>
.
I have found these functions helpful in all kinds of situations:
<Button>
, and then derive various variants from it, for example:
<PrimaryButton>
or <SecondaryButton>
.
<Button>
.withVariants
reduce boilerplate and clarify intent for
such tasks.children
of a component.curry
, that have been specialized for React components.
curry
combinator for functions is useful enough to deserve
its own name, so too for assumeProps
when dealing with React components.A Contravariant
instance for Effect and a bunch of combinators. If
you squint hard you will see they are all just specializations of mapProps
:
appendChildren
assumeProp
assumeProps
modCssVar
mapProp
mapProps
modChildren
modProp
modStyle
omitProps
prependChildren
renameProp
renameProps
requireProp
unfoldProp
withDefault
withDefaultStyle
withStyle
withVariants