npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

reuse

v2.0.0

Published

Reuse different React components to create new ones

Downloads

2,719

Readme

Installation

npm i reuse

Thanks to @eldargab for the package name on npm.

Why

This enables (sub)atomic design approach.

When using classic CSS, we have a powerful way to compose "stylesheet components" by applying multiple class names to our HTML elements (.btn, .large, .rounded etc.). But, by doing that in React, which has its own component structure, we'll have conflicting component structures.

Reuse solves it by combining React components together as if they were CSS classes. This also means that not only style will be composed, but also JavaScript behavior, like React lifecycle methods and event handlers.

Usage

Reuse simply exports a factory method that returns a React component. You can leverage that method in two ways: augmentation and combination.

Examples

Augmentation

The component returned by the use factory will expect a use prop:

import use from "reuse";

const Box = use();

<Box />; // null
<Box use="div" />; // <div />
<Box use={Link} />; // <Link />

You can create the component with a default element:

const Box = use("div");

<Box />; // <div />
<Box use="span" />; // <span />

You can create the component with another component. Just make sure to render the use prop as the underlying element and pass the other props down (at least, when use isn't a string – HTML element):

import React from "react";
import use from "reuse";

// grab the `use` prop and pass down other props
const Base = ({ use: T = "div", ...props }) => <T {...props} />;

const Box = use(Base);

<Box />; // <div />
<Box use="span" />; // <span />

const BoxSpan = use(Box, "span");
<BoxSpan />; // <span />

You can use Base to filter custom props when use is a string using @emotion/is-prop-valid, for example.

Combination

Let's create some components:


// Using styled-components
const Paper = styled(use("div"))`
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.30);
`;

// Using class names
const Rounded = use(({ use: T, ...props }) => (
  <T
    {...props}
    className={`rounded ${props.className}`}
  />
), "div");

// Using inline styles
const Button = use(({ use: T, ...props }) => (
  <T
    {...props}
    style={{
      padding: "0 1em",
      lineHeight: "2.5em",
      background: "#3f51b5",
      color: "white",
      ...props.style
    }}
  />
), "button");

Once you have a few of those components, you can combine them using the same use methods:

import use from "reuse";
import { Rounded, Paper, Button } from "../components";

// with factory
const RoundedPaperButton = use(Rounded, Paper, Button);
<RoundedPaperButton />; // <button style="..." class="..." />
<RoundedPaperButton use="div" />; // <div style="..." class="..." />

// with prop
<Rounded use={[Paper, Button]} /> // <button style="..." class="..." />
<Rounded use={[Paper, Button, "div"]} /> // <div style="..." class="..." />

Note that the underlying HTML element will always be based on the last component you pass to use.

FAQ

These are equivalent implementations:

Render props

<Paper>
  {paperProps => (
    <Rounded {...paperProps}>
      {roundedProps => (
        <Button {...roundedProps}>
          {buttonProps => (
            <button {...buttonProps}>Button</button>
          )}
        </Button>
      )}
    </Rounded>
  )}
</Paper>

High-order components

withPaper(withRounded(withButton(props => <button {...props}>Button</button>)));

Reuse

use(Paper, Rounded, Button);
// or
<Paper use={[Rounded, Button]} />

When using render props or HOCs, you have to stick with their static (HOC) or dynamic implementation (render prop). With Reuse, besides simplicity, you can use both depending on your needs.

License

MIT © Haz