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

https://github.com/ilyalesik/react-overrides

Pass props to internal elements of React component
https://github.com/ilyalesik/react-overrides

react

Last synced: over 1 year ago
JSON representation

Pass props to internal elements of React component

Awesome Lists containing this project

README

          

# react-overrides

[![Build Status](https://travis-ci.org/ilyalesik/react-overrides.svg?branch=master)](https://travis-ci.org/ilyalesik/react-overrides)
[![npm version](https://img.shields.io/npm/v/react-overrides.svg)](https://www.npmjs.com/package/react-overrides)
[![npm downloads](https://img.shields.io/npm/dt/react-overrides.svg)](https://www.npmjs.com/package/react-overrides)

Let's create `CommonButton` component with `react-overrides`:
```javascript
import o from "react-overrides";

export const CommonButton = props => (

{props.children}

);
```

Next, we can pass props to internal elements of `CommonButton` by passing `overrides` prop:
```javascript
export const LinkButton = props => (
tag. Typical for CSS-in-JS solutions.
href: props.href // add href attribute to element
}
}
}}
/>
);
```
So we extend the `CommonButton` by creating a `LinkButton` that has *link* behavior.

Try at CodeSandbox:

[![Edit react-overrides](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/n8m65940l)

It is also possible to replace the entire component:
```javascript
export const LinkButton = props => (

);
```


Sponsored by Lessmess

## Motivation

There is a need for pass props directly to elements, or replace his component.
Here's some examples of when you need it:
* You create UI library, and want to provide wide customization abilities for components. [Base UI](https://baseui.design/) library used this approach.
* You need *unified* way to pass any props (for example, ARIA attributes) to elements of components.
* Your components can have many internal elements and it can be inconvenient to add a prop to component every time you just need to forward the prop to an internal element.

## Installation

Install core package and babel plugin with yarn:

```
yarn add react-overrides
yarn add babel-plugin-react-overrides --dev
```

Or with npm:

```
npm i react-overrides --save
npm i babel-plugin-react-overrides --save-dev
```

Further, add `react-overrides` to your `.babelrc` configuration:
```json
{
"plugins": ["babel-plugin-react-overrides"]
}
```

## Usage

Create extendable component by passing the default export
from `react-overrides` package to the component to be extended.

*Example*:

```javascript
import React, {useState} from "react";
import o from "react-overrides";
import {Container, Value, OptionsContainer, Option} from "...";

export const Select = (props) => {
const {opened, setOpened} = useState(false);

return setOpened(!opened)}>
{props.currentValue}
{opened &&
{props.values.map(({label, id}) => (
props.onSelect(id)} key={id}>{label}
))}
}

};
```

Extend with component through passing props of internal component:
```javascript
import React from "react";
import {Select} from "./Select"

const BigOptionSelect = (props) => {
return
}
```

#### Replace internal components

You can replace the internal component with a custom one:
```javascript
import React from "react";
import {Select} from "./Select"
import {FancyGrid} from "./fancy-grid";

const FancyGridSelect = (props) => {
return
}
```

#### Access to individual props

```javascript
import React from "react";
import o from "react-overrides";
import c from "classnames";
import "./button.scss";

const Button = props => {
const Container = (props) => ;
const Text = (props) => ;

return (


{props.children}


);
};
```

#### Flow support
You can use `ExtractOverrides` type props helper for infer overrides prop type from components types.
```javascript
// @flow
import * as React from "react";
import o, { type ExtractOverridesProps } from "react-overrides";

const Option = (props: { a: 1 | 2, b: string }) => {
return

{props.b + 2 * props.a}
;
};

const Container = (props: { children?: React.Node }) => {
return

{props.children}
;
};

const OverridableProps = {
Option,
Container
};
type TOverridesProps = ExtractOverridesProps;

const Select = (props: { overrides: TOverridesProps }) => {
return (

{/* For access to individual prop used o()., o. throw Flow error */}


);
};

const OverridedSelect = () => {
return (

);
};

// throw flow error:
const OverridedSelectWrong = () => {
return (

);
};
```

# Acknowledgements
This library inspired by article
[Better Reusable React Components with the Overrides Pattern](https://medium.com/@dschnr/better-reusable-react-components-with-the-overrides-pattern-9eca2339f646).

Thanks [@ai](https://github.com/ai) for review the documentation.