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

react-delegate-component

v1.0.0

Published

A component that makes renderProps great, allowing callers to use functional and class components with a default.

Downloads

1,751

Readme

React Delegate Component

Delegation is a powerful design pattern that allows callers to replace and extend behavior through an API. In React, we can delegate how we render UI in Components through props, where the internal component can call a prop function to return elements. This pattern is commonly referred to as renderProps.

This pattern works well for sharing logic and building flexible Components and UI libraries. However, if you use a lot of renderProps you start to realize the awkwardness of supporting the following use-cases.

  • Rendering both functions and class components.
  • Providing a default delegate.
  • Being able to render that default from within your delegate (wrapping it, etc).

These are all reasonable things you will likely want to provide functionality for, especially in a UI library. Thankfully, react-delegate-component provides the Delegate component to support all these use-cases easily and efficiently.

<Delegate
  to={this.renderItem}
  default={DefaultItem}
  props{{ label: this.props.items[i] }}
/>

If you are unfamiliar with delegation as a pattern, I recommend reading through the motivation section in this README and reading up on renderProps. Note that many examples in the wild only use a single renderProp (render or children), but you can have many depending on what you need to delegate.

This Component will work for both React and React Native as it does not render any specific markup.

Installation

Install with the package manager of your choice:

# using yarn
yarn add react-delegate-component

# using npm
npm install --save react-delegate-component

Import the component with the module system of your choice:

import Delegate from "react-delegate-component";

// or

const Delegate = require("react-delegate-component");

Usage

Use a delegate in your component to yield a convenient API for any consumers of your component. For example:

A fancy list where items are delegated

We'll provide a default, which can be replaced or extended.

// Definition
function DefaultItem({ label }) {
  return (
    <div className="fancy-item">
      {label}
    </div>
  );
}

class FlexibleList extends React.Component {
  static propTypes = {
    labels: arrayOf(string).isRequired
    renderItem: func
  };

  render() {
    return (
      <div {...fancyStyles}>
        {labels.map(label => (
          <Delegate
            to={this.renderItem}
            default={DefaultItem}
            props={{ label }}
          />
        ))}
      </div>
    );
  }
}

// Usage
const items = ["Apples", "Bananas", "Carrots"];


// Default list
<FlexibleList items={items} />

// Replacing inline
<FlexibleList items={items} renderItem={({ label }) => <div></div>} />

// Replacing with any Component (functional or class)
<FlexibleList items={items} renderItem={EvenFancierItem} />

// Extending default with additional markup
<FlexibleList
  items={items}
  renderItem={({ label, Default }) => <div><Checkbox /><Default></div>}
/>

// Extending default with additional markup, overriding label on Default
<FlexibleList
  items={items}
  renderItem={({ label, Default }) => <div><Default label={`${label}!!!`}></div>}
/>

API

to (aliases: render, children)

type: ({ Default?, ...props }) => node
default: undefined

The prop which represents the passed in delegate.

Takes a function or class component. This function/Component is passed all of the props from the props prop. It is also passed a special prop called Default, which can be rendered by the delegate. The Default component already has all props curried onto it. These props can be overridden in the delegate.

This function should return any React-renderable (propType: node).

If undefined, the Component will render the default prop if available, or nothing (returning null).

default

type: (props) => node
default: undefined

Takes a function or class component. Just like to, this function/Component is passed all of the props from the props prop.

This function should return any React-renderable (propType: node).

If undefined, the Component will render the render prop if available, or nothing (returning null).

props

type: object
default: {}

An single object which represents all props to pass to both the to and default props.

passDefault

type: boolean
default: true

A prop which signifies whether the Default prop should be passed down to the delegate. Usually you want this to be on, but there are some cases where you don't want to expose the Default to callers.

Why not just add default props and be done with it?

If you don't need to render the default in you delegate and still want to support class components, you don't need this package and can do something like this:

class ManualDelegation extends React.Component {
  static defaultProps = {
    renderItem: DefaultItem
  };

  render() {
    const RenderItem = this.props.renderItem;
    return <RenderItem some={props} />
  }
}

Make sure you render the delegate through JSX, otherwise you will not be able to support class components. In large codebases, I have found that it is easy to get delegates wrong with accidental extra arguments or non-JSX calls. I recommend using this package to be explicit and fool-proof, and to generally provide the Default as part of your API.