overrides

1.2.0 • Public • Published

Overrides for React

This project provides a React "Higher-Order Component" and a React "Hook" that implemenets the "overrides" pattern described in this article https://medium.com/@dschnr/better-reusable-react-components-with-the-overrides-pattern-9eca2339f646 and used throughout the Base Web component library. The Hook and Higher-Order Component avoids manual prop spreading required when using getOverrides/getComponents directly (but we also expose our version of getOverrides/getComponents if you want to use them)

Why Overrides?

Overrides can be thought of as "render props on steriods". Instead of adding a render prop for each sub-component of your component, you set up overrides which are activated using the overrides prop. In exchange, you get both the equivalent of a render prop (by using a component override), as well as shortcuts to override the style or props of the default sub-component implemention. This is even more powerful when you consider nested overrides.

Why the overrides library?

The example implementation described in the above article and the implementation in Base Web requires a fair amount of manual object destructuring and prop spreading. This work can be encapsulated in a Hook or Higher-Order Component, which is what this library does.

react-overrides is another project that implements this pattern, but it requires a custom Babel plugin.

Features

  • style override (merged with existing style): { Name: { style: { color: "red" } } }
  • style override can be a function: { Name: { style: ({ isOpen }) => ({ color: isOpen ? "green" : "red" }) } }
  • props override: { Name: { props: { "aria-label": "name" } } }
  • component overrides: { Name: { component: Replacement } }
  • component override shorthand: { Name: Replacement }
  • nested overrides: { Name: { SubName: { SubReplacement } }, { Name: { SubName: { style: { color: "red" } } }, etc
  • getOverrides and getComponents can also be used directly

Examples

import { withOverrides, useOverrides } from "overrides"
// or...
import withOverrides from "overrides/with"
import useOverrides from "overrides/use"

const defaultComponents = {
  Bar: ({ style, message }) =>
    <div style={style}>{message}</div>
};

// Hook:
const Foo = ({ overrides, ...props }) => {
  const { Bar } = useOverrides(defaultComponents, overrides);
  return <Bar message="hello" />;
};

// Higher-Order Component:
const Foo = withOverrides(defaultComponents)(
  ({ Bar }) =>
    <Bar message="hello" />
);

// Higher-Order Component on class component with decorator:
@withOverrides(defaultComponents)
class Foo extends React.Component {
  render() {
    const { Bar } = this.props;
    return <Bar message="hello" />;
  }
}

// Usage:

// component override:
<Foo overrides={{ Bar: { component: CustomBar } }} />

// component override shortcut:
<Foo overrides={{ Bar: CustomBar }} />

// style override:
<Foo overrides={{ Bar: { style: { color: "red" } } }} />

// style override with function:
<Foo overrides={{ Bar: { style: ({ isOpen }) => ({ color: isOpen ? "green" : "red" }) } }} />

// prop override:
<Foo overrides={{ Bar: { props: { message: "goodbye" } } }} />

// nested overrides:
<Foo overrides={{ Bar: { Baz: { props: { message: "goodbye" } } } }} />

Dependencies (0)

    Dev Dependencies (10)

    Package Sidebar

    Install

    npm i overrides

    Weekly Downloads

    93

    Version

    1.2.0

    License

    MIT

    Unpacked Size

    21.5 kB

    Total Files

    14

    Last publish

    Collaborators

    • tlrobinson