Ecosyste.ms: Awesome

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

Awesome Lists | Featured Topics | Projects

https://github.com/dgca/react-polly

๐Ÿ›  A polymorphic component factory for React โš›๏ธ
https://github.com/dgca/react-polly

react react-native reactjs

Last synced: 7 days ago
JSON representation

๐Ÿ›  A polymorphic component factory for React โš›๏ธ

Awesome Lists containing this project

README

        

# `react-polly`

๐Ÿ›  **polymorphic** _component factory_ for React โš›๏ธ

**[Bootstrapped with `dts-cli`](https://github.com/weiran-zsd/dts-cli)**

## Status

[![stability-experimental](https://img.shields.io/badge/stability-experimental-orange.svg)](https://github.com/mkenney/software-guides/blob/master/STABILITY-BADGES.md#experimental)

This library is pre-release, as I'm still trying to work out the best API for this. Feedback is very apprecaited! If you have any ideas, please submit an issue or open a PR ๐Ÿ™

## What it does:

`react-polly` provides a quick and easy way to create polymorphic componentsโ€”that is, components that can return different underlying elements based on an `as` prop passed in by the caller.

Additionally, it handles ref forwarding via `React.forwardRef`, and it manages merging additional prop types based on the provided `as` prop.

## How to use it:

_Note: This assumes you're using TypeScript._

**Install:** `npm install react-polly` or `yarn add react-poly`

`polly` is a generic function that takes two type arguments and one regular function argument.

The type arguments specify the default element type your component will return, and the prop types that your component will handle.

The main function argument is your component definition.

Note that although you must use the same default element type as the first type argument, and as the default value for your `as` prop.

```tsx
import polly from 'react-polly';

type TextProps = {
color?: "black" | "red" | "blue";
children: React.ReactNode;
};

// Here we create a polymorphic component that returns a by default.
const Text = polly<"span", TextProps>(function Text(
{
// You must provide the same default value for the `as` prop as you
// passed to the first generic type argument.
// You must also rename the `as` prop to an Uppercase word cause React
// component names must be capitalied.
as: Component = "span",
color = "black",
children,
...rest
},
ref?
) {
return (

{children}

);
});

type YellerProps = {
children: React.ReactNode;
exclamationCount: number;
};

// This is a regular component for demo purposes below.
function Yeller({ children, exclamationCount, ...rest }: YellerProps) {
return (

{children}
{Array.from({ length: exclamationCount })
.map(() => "!")
.join("")}

);
}

function Demo() {
return (


react-polly


{/* This will render a element */}
Hello! I'm a polymorphic element.


{/* This will render a tag */}

I can render any type of element that you specify via my `as` prop.



{/* This will render a Yeller component */}

I can even render as other React Components



);
}
```

## Appendix

* Shoutout to Ben Ilegbodu for [this blog post](https://www.benmvp.com/blog/forwarding-refs-polymorphic-react-component-typescript/) which was super useful when writing this library.