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-grouped-children

v0.1.4

Published

Enables creation of grouped component inheritance hierarchies for React components

Downloads

291

Readme

react-grouped-children

A React library to allow passing multiple children groups to a component using classic React component inheritance hierarchies instead of attributes.

Table of Contents

Installation

npm install react-grouped-children

or

yarn add react-grouped-children

Usage

Defining Children Specification

Create a childrenSpec object where each key is a grouping component name and its value is the component itself.

If you don't have a component for a particular group, you can set its value to null. If value is not set a proxy component will be generated and its children passed to primary component props, not the proxy component.

const childrenSpec = {
  Header: Header,
  Footer: null,
} as const;

Modifying Component

Wrap your component (main component) with withGroupedChildren and pass childrenSpec as the second argument to define grouping components.

import { withGroupedChildren } from 'react-grouped-children';

const MyComponentInternal: React.FC<MyComponentProps & GroupedChildrenProps<typeof childrenSpec>> = ({
  header,
  footer,
  ...
}) => ...

const MyComponent = withGroupedChildren({ childrenSpec })(MyComponentInternal);

With childrenSpec defined as in the example above header prop will contain an array with all instances of Header component and footer prop will be set to an array of children of the generated proxy component.

NOTE: be mindful that react may pass children as single child or as an array, so footer may contain array of arrays. To properly control this you can define traverseChildren function in config or do proper parsing in the component. This project does not address it as it will be fully compatible with React.ReactNode type and React can handle it properly if you pass it as is when you rendering the main component.

NOTE: You may have some challenges with key property if you pass elements to render return "as-is". Most like this will happen only if your custom childrenToArray function does not assign keys properly.

Using Children Groups and HOC

Now, you can pass children group components to your component as follows:

...
return (
  <MyComponent>
    <MyComponent.Header>
      This is header
    </MyComponent.Header>
    <MyComponent.Footer>
      This is footer 1
    </MyComponent.Footer>
    <MyComponent.Footer>
      This is footer 2
    </MyComponent.Footer>
  </MyComponent>
)
...

Configuration

You can configure the behavior of withGroupedChildren by passing an optional config object. Mode details are in JSDoc comments of Config type (./src/types.ts)

childrenSpec

Specification which defines children components. Should represent object with keys in Pascal case to define groping component name. Value can be set to an implementation of grouping component or null to use default component generated by default factory.

childrenToArray

A custom method to convert React component initial children to array on preprocessing stage. Use when you want to flatten children. The function must always returned a cloned array of children as it will be mutated. If not defined, React.Children.toArray is used by default.

getComponentName

A custom HOC name generation factory. Returns custom component name.

proxyComponentFactory

A factory which accepts current key of specification object returns a custom implementation of Proxy component.

⚠ Be mindful that this factory should return a new component every for every separate key. This is because the default componentMatcher is matching types by reference, not by display name or anything else. To change this define your own componentMatcher

traverseChildren

A custom method to traverse children from Proxy Component. This method is generic, return type should match with the second generic (T) parameter of GroupedChildrenProps

componentMatcher

A custom component matcher

Limitations

Static Properties/Methods

To enable grouping functionality withGroupedChildren adds grouping components as static properties to resulting HOC. You need to ensure that you copy them over if you use other HOC on top. More details here

Why?

in classic React when you want to divide children into groups to use them separately in different sections of your app you need to pass them as React.ReactNode attributes which often make code reading challenging, especially when you need to have many attributes like this:

<MyComponent
  group1={
    <div>
      <Head>Some content</Head>
      <Body>
        Some bigger content
        <ul>
          {elements.map((e) => <li key={e}>{e}</li>)}
        </ul>
      </Body>
    <div>
  }
  group2={
    <div>
      <Footer>
        <FooterItem>Item 1</FooterItem>
        <FooterItem>Item 2</FooterItem>
        <FooterItem>Item 3</FooterItem>
      </Footer>
    <div>
  }
>
  {restChildren}
</MyComponent>

With this package it becomes more transparent and look more HTML-ish:

<MyComponent>
  <MyComponent.Group1>
    <div>
      <Head>Some content</Head>
      <Body>
        Some bigger content
        <ul>
          {elements.map((e) => <li key={e}>{e}</li>)}
        </ul>
      </Body>
    <div>
  </MyComponent.Group1>
  <MyComponent.Group2>
    <div>
      <Footer>
        <FooterItem>Item 1</FooterItem>
        <FooterItem>Item 2</FooterItem>
        <FooterItem>Item 3</FooterItem>
      </Footer>
    <div>
  <MyComponent.Group2>
  {restChildren}
</MyComponent>

or in scenarios like this

<MyList>
  <MyList.Item>Item 1<MyList.Item>
  <MyList.Item>Item 2<MyList.Item>
  <MyList.Item>Item 3<MyList.Item>
  <MyList.Item>Item 4<MyList.Item>
  <MyList.Item>Item 5<MyList.Item>
  <MyList.Heading>Heading Line</MyList.Heading>
  <MyList.Footer>Heading Line</MyList.Footer>
</MyList>

and access children as classic attributes:

const MyList: React.FC = ({ item, heading, footer }) => {
  ...
  return (<div>
    {heading}<br />
    <ul>
      {item.map((i) => <li>{i}</li>)}
    </ul>
    {footer}
  </div>)
}

License

MIT

Copyright (c) 2023 Alexandr Yeskov