Creating Extensible React UI Components

Sedang Trending 2 bulan yang lalu

Build extendable and scalable React components successful 2024!

Lakindu Hewawasam

Bits and Pieces

If you’re building a creation system, aliases a group of UI components it’s important to make judge that they’re extensible. Simply put, you request to dainty your UI components arsenic “base components” pinch small to nary dependencies, but pinch galore dependents.

But, what does this mean?

For instance, see nan constituent character below:

If you look astatine nan Typography and nan Link components, you tin spot that:

  1. These React components are being utilized arsenic foundational blocks to build nan remainder of nan creation system.
  2. These components person nary limitations pinch components. Instead, these components person dependents, wherever each different constituent successful nan UI library/ creation strategy uses these 2 components to create different components.

But, sometimes, you tin make your guidelines components dangle connected definite libraries. For example, if you were building your guidelines components pinch Material UI, you’d apt person your guidelines components depending connected MUI.

But isolated from that, you wouldn’t person your guidelines components dangle connected different components arsenic this looses its extendibility.

Pst, if you wish to cheque retired nan codification to creating an extendible component, cheque retired my Bit Scope.

The Bit Scope that comprises of extendible UI components

To make a constituent extendible, you request to make judge that it has 3 properties:

  1. A constituent API
  2. A theme
  3. A customizable nature

Let’s return a look astatine each spot successful item to understand really it genuinely makes your components extendible. To do so, let’s create a React constituent pinch Bit.

“Why Bit?” — You mightiness wonder.

Well, deliberation of it for illustration this. If you’re building a UI Library, you’d apt want to negociate your components independently right?

For instance, different users mightiness want to update components that are portion of your room and propagate nan changes to each of its usages right?

And, that’s precisely wherever Bit shines.

Bit is simply a next-generation build strategy for composable software. It lets you design, develop, build and type components successful an isolated abstraction while it’s CI Server — Ripple CI propagates changes that you make to a azygous constituent crossed nan constituent tree.

With this, you’d beryllium capable to create independent React components for your UI room and support them successful isolation. So, let’s create a React constituent pinch Bit and spot really we tin make it extendible.

Step 01 — Pre-requisites

To create a React constituent pinch Bit, let’s first instal Bit. Use Bit’s type head (BVMM) to instal Bit globally and past initialize a workspace.

The workspace will fto america build our components.

# instal bit
npx @teambit/bvm instal

# initialize workspace
bit init

Note, workspaces aren’t tied to a language. You tin build different components for illustration Node.js, Angular, Next.js and React successful a azygous workspace utilizing Bit Environments.

Once you’ve done this, you should spot nan output:

Step 02 — Creating a React Component

Next, let’s create a React component. To do so, tally nan command:

bit create respond buttons/button

This will create a constituent named Button, and will make nan output:

Next, tally spot commencement to motorboat your Bit server. All changes you make to components will beryllium visible present successful existent time.

Now, let’s spot really we tin make this extendible.

Step 03 — Making Components Extendible

Now, arsenic a recap, an extendible constituent has 3 properties:

A Component API

You request to guarantee that your constituent has an API that’s disposable for different components to use. This tin beryllium done by creating an index.ts record for your constituent and exporting each of its Type definitions and Component definition.

With Bit, this is already achieved erstwhile you create a component. For instance, inspect nan Button component:

It has an index.ts record that erstwhile observed will show nan following:

export { Button } from './button';
export type { ButtonProps } from './button';

As you tin see, nan Props and nan Component meaning has been exported for consumers to use. So, by doing so, consumers tin create their extended Props that combines nan Props of nan Button onto their implementation.

For example, if you had a 2nd React constituent named IconButton that utilized nan Button, you'd request to guarantee that your IconButton tin judge ButtonProps. This tin achieved by doing nan following:

import React, { ReactNode } from 'react';
import { Button, ButtonProps } from '@dummyorg/extendability.buttons.button';

export type IconButtonProps = {
children?: ReactNode;
} & ButtonProps;

export usability IconButton({ children, ...rest }: IconButtonProps) {
return (
<div>
{children}
<Button
{...rest}
/>
</div>
);
}

As you tin see, we’ve imported nan ButtonProps to nan IconButton constituent and we’ve mixed nan Prop types together pinch nan IconButtonProps to guarantee that nan IconButton tin judge nan ButtonProps.

So, by making judge that your components person an exposed API, you let different components to usage nan guidelines components to its fullest potential.

Therefore, your implementation would look thing for illustration this:

By utilizing nan Button constituent API, we make our constituent adhd extendible behaviour depending connected nan discourse it’s being used.

To position nan afloat implementation of nan IconButton, cheque retired this Bit Component.

A Theme

Base components request to beryllium themeable to support consistency successful style, crossed compositions.

You request to style your constituent utilizing JS variables aliases CSS civilization props that correspond to your theme schema. Additionally, you tin supply each prop pinch a fallback value.

For instance, if you were utilizing an MUI Button, you’d person an implementation for illustration this successful your Button component:

import React from 'react';
import { Button arsenic MUIButton, ButtonProps arsenic MUIButtonProps } from '@mui/material';

export type ButtonProps = {
} & MUIButtonProps;

export usability Button({ children, version = 'contained', ...rest }: ButtonProps) {
return (
<MUIButton
variant={variant}
{...rest}
>
{children}
</MUIButton>
);
}

If you look closely, there’s a version prop that I'm initializing pinch a default worth of contained. By doing so, I'm enforcing that immoderate user that uses nan Button constituent pinch its default behaviour render a contained button, arsenic follows:

As you tin see, nan Button constituent now launches connected contained authorities arsenic a default.

By doing so, you make judge that your constituent usages stay accordant erstwhile utilized pinch nary civilization implementation by nan consumer.

To checkout nan afloat implementation, cheque retired this Bit Component.

A Customizable Nature

If you person a constituent that’s customizable, there’s a higher chance of group utilizing your constituent to make caller ones.

For instance, cheque retired this constituent tree:

A Sample Component Tree

The Typography constituent has been utilized by each of these components for different implementations.

But, really is this possible?

Well, you person to creation your constituent successful a measurement wherever it tin beryllium extended for others to use. This tin beryllium done successful 2 ways:

  1. Style Overrides
  2. Attribute Overrides

I’ve touched these 2 topics towards nan commencement of nan article, however, let’s research this further successful this section.

Style Overrides

You request to creation your constituent successful specified a measurement that it should beryllium capable to judge “style” overrides.

To execute this, person an optional className aliases style prop included successful nan constituent API arsenic shown below:

export type ButtonProps = {
/**
* civilization style entity for style overrides
*/
style?: React.CSSProperties
} & MUIButtonProps;

You tin update nan prop meaning arsenic shown above. By doing so, you fto your consumers walk an optional style prop that they tin usage to customize nan CSS of nan component. Afterward, usage nan constituent arsenic shown below:

export usability Button({ children, style, version = 'contained', ...rest }: ButtonProps) {
return (
<MUIButton
variant={variant}
style={style} // use nan style
{...rest}
>
{children}
</MUIButton>
);
}

Pass nan style prop to nan original constituent arsenic shown supra for nan civilization styles to beryllium applied.

Attribute Overrides

We’ve already done this, but you tin see a ...rest (spread) prop successful your component's API to make it extendable by further attributes.

You tin usage this to target autochthonal HTML prop attributes specified arsenic aria attributes that mightiness beryllium difficult to remember. A constituent that leverages this would look arsenic below:

import React, { JSX } from 'react';
import { Button arsenic MUIButton, ButtonProps arsenic MUIButtonProps } from '@mui/material';

export type ButtonProps = {
/**
* civilization style entity for style overrides
*/
style?: React.CSSProperties
} & MUIButtonProps & JSX.IntrinsicElements['button'];

export usability Button({ children, style, version = 'contained', ...rest }: ButtonProps) {
return (
<MUIButton
variant={variant}
style={style}
{...rest}
>
{children}
</MUIButton>
);
}

As shown above, I’ve leveraged nan JSX.IntrinsicElements['button'] meaning to use each autochthonal HTML Button props to this Button. Next, pinch nan usage of nan ...rest being applied connected MUIButton applies each of nan props passed from nan parent.

For instance, see this composition:

export const ButtonWithOnClick = () => {
return (
<Button
onClick={() => alert('You Clicked Me')}
>hello world!</Button>
);
}

We did not specify an onClick prop for nan Button. However, our constituent API still allows this. This is because we've leveraged type aggregating nan applied each of nan styles utilizing spreading, that creates nan pursuing output:

And location we person it! It’s that easy to create extendible React components successful 2024.

All you person to retrieve are 3 things — A Component API, A Theme and a Customizable Nature

If your constituent has these properties, your constituent is extendible by nature.

If you wish to cheque retired nan afloat implementation of this article, cheque retired my Bit Scope.