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
- Host: GitHub
- URL: https://github.com/ilyalesik/react-overrides
- Owner: ilyalesik
- Created: 2018-12-27T11:33:44.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2023-01-03T16:22:25.000Z (over 3 years ago)
- Last Synced: 2024-10-20T14:32:37.801Z (over 1 year ago)
- Topics: react
- Language: JavaScript
- Homepage:
- Size: 903 KB
- Stars: 28
- Watchers: 3
- Forks: 1
- Open Issues: 23
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# react-overrides
[](https://travis-ci.org/ilyalesik/react-overrides)
[](https://www.npmjs.com/package/react-overrides)
[](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:
[](https://codesandbox.io/s/n8m65940l)
It is also possible to replace the entire component:
```javascript
export const LinkButton = props => (
);
```
## 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.