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-cmp-selector

v1.0.5

Published

A lightweight utility for filtering and selecting React components based on specified attributes and values

Downloads

42

Readme

react-cmp-selector

react-cmp-selector is a lightweight utility for filtering and selecting React components based on specific attributes and values. It allows developers to dynamically query and manipulate components within a React component tree, enabling more flexible and dynamic rendering logic.

Features

  • Attribute-Based Component Selection: Easily select and manipulate components by specifying a specific attribute and value.
  • Supports Additional Props: Clone and extend components with additional props when rendering.
  • Debugging: Optional debugging to log matched components during development.

Installation

To install the package, run:

npm install react-cmp-selector

or using yarn:

yarn add react-cmp-selector

Usage

Basic Usage

Suppose you have a set of child components within a parent component, and you want to select a specific child component based on a data-slot attribute. You can use react-cmp-selector to do this.

Example

import React from "react";
import getCmpByAttr from "react-cmp-selector";

function ParentComponent({ children }: { children: React.ReactNode }) {
  const headerComponent = getCmpByAttr({
    children,
    value: "header", // Select component with data-slot="header"
  });

  const bodyComponent = getCmpByAttr({
    children,
    value: "body", // Select component with data-slot="body"
  });

  const footerComponent = getCmpByAttr({
    children,
    value: "footer", // Select component with data-slot="body"
  });

  return (
    <div className="bg-red p-auto">
      {headerComponent}
      <div ClassName="bg-blue mt-10">{bodyComponent}</div>
      {footerComponent}
    </div>
  );
}

export default function App() {
  return (
    <ParentComponent>
      <div data-slot="header">This is the header</div>
      <div data-slot="body">This is the body</div>
      <div data-slot="footer">This is the footer</div>
    </ParentComponent>
  );
}

Limitation with Next.js Routes

While react-cmp-selector works well within the same component tree (such as nested components), there is a known limitation when using it with Next.js routing.

In Next.js, layouts and pages are handled separately. When components are passed from a parent layout to a child page, the data-slot attribute may not be detected as expected. This is because of the way Next.js manages the component hierarchy between layouts and pages. As a result, getCmpByAttr will not work as intended between layouts and pages.

Example (Next.js Limitation)

If you attempt to use react-cmp-selector across a Next.js layout and a page like this:

// Layout.js
export default function Layout({ children }) {
  return <div>{children}</div>;
}

// Page.js
import getCmpByAttr from "react-cmp-selector";

export default function Page({ children }) {
  const headerComponent = getCmpByAttr({
    children,
    value: "header",
  });

  return <div>{headerComponent}</div>;
}

It will not detect components passed from the layout due to the separation of layouts and pages in Next.js.

Workaround for Next.js

For Next.js, react-cmp-selector will work properly when used within the same component (i.e., nested components on the same page), but it cannot detect components passed between a layout and a page. To handle this, you can pass components explicitly through props or use context to share component references between the layout and pages.

Example (Next.js Workaround)
// Layout.js
import { createContext, useContext } from "react";

const SlotContext = createContext();

export function Layout({ children }) {
  return (
    <SlotContext.Provider value={{ header: "Header Content" }}>
      <div>{children}</div>
    </SlotContext.Provider>
  );
}

export function useSlots() {
  return useContext(SlotContext);
}

// Page.js
import { useSlots } from "./Layout";

export default function Page() {
  const slots = useSlots();

  return (
    <div>
      <header>{slots.header}</header>
      <div>Page Content</div>
    </div>
  );
}

Summary

  • Works well in React (React Router): You can use react-cmp-selector for selecting components within the same component tree, such as nested components or when rendering children directly.
  • Limitations in Next.js: It does not work as expected when selecting components between Next.js layouts and pages due to the separation of components between layout and page rendering.
  • Workaround for Next.js: Use context or pass components explicitly through props to handle layouts and pages in Next.js.

Use Cases

  1. Dynamic Rendering:

    • Selectively render components based on specific criteria, such as user roles, permissions, or other dynamic conditions.
  2. Custom Layouts:

    • Create custom layouts where different components are placed in specific slots. Use react-cmp-selector to retrieve and place these components in the correct positions.
  3. Component Wrapping:

    • Wrap selected components with additional functionality or styling by cloning them with extra props.

Advanced Usage

Passing Additional Props

You can pass additional props to the selected component using the props option:

const enhancedHeader = getCmpByAttr({
  children,
  value: "header",
  props: { className: "enhanced-header" }, // Add additional props
});

Debugging

Enable debugging to log the selected component to the console:

const headerWithDebug = getCmpByAttr({
  children,
  value: "header",
  debug: true, // Enable debugging
});

Parameters:

  • children: ReactNode - The children components to search through.
  • attr: string (optional) - The attribute to search by. Defaults to data-slot.
  • value: string - The value of the attribute to match.
  • props: Record<string, any> (optional) - Additional props to pass to the matched component.
  • debug: boolean (optional) - If true, logs the matched component(s) to the console.

Returns:

  • ReactNode | null - The matched component or null if no match is found.

Contributing

Contributions are welcome! Please open an issue or submit a pull request if you have suggestions or improvements.

License

This project is licensed under the MIT License. See the LICENSE file for details.