JSPM

@domeadev/react-elements-renderer

0.0.1
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 2
  • Score
    100M100P100Q18094F
  • License MIT

A flexible React component for rendering hierarchical/nested data structures with customizable rendering logic and automatic recursion handling.

Package Exports

  • @domeadev/react-elements-renderer

Readme

React Elements Renderer

A flexible React component for rendering hierarchical/nested data structures with customizable rendering logic and automatic recursion handling.

Features

  • 🔄 Recursive Rendering: Automatically handles nested/hierarchical data structures
  • 🎯 Type Safe: Full TypeScript support with generic types
  • 🎨 Flexible: Completely customizable element rendering
  • 🔑 Key Management: Built-in key generation for React reconciliation
  • 🌳 Tree Structures: Perfect for trees, menus, file systems, organizational charts, etc.
  • Lightweight: Zero dependencies (except React)

Installation

npm

npm install @domeadev/react-elements-renderer

yarn

yarn add @domeadev/react-elements-renderer

pnpm

pnpm add @domeadev/react-elements-renderer

Basic Usage

import { ElementsRenderer } from "@domeadev/react-elements-renderer";

interface MenuItem {
  id: number;
  label: string;
  children?: MenuItem[];
}

const menuItems: MenuItem[] = [
  {
    id: 1,
    label: "Home",
  },
  {
    id: 2,
    label: "Products",
    children: [
      { id: 21, label: "Laptops" },
      { id: 22, label: "Phones" },
    ],
  },
];

function MenuComponent() {
  return (
    <ElementsRenderer
      elements={menuItems}
      getElementKey={(item) => item.id}
      getChildElements={(item) => item.children}
      renderElement={({ element, children }) => (
        <div>
          <span>{element.label}</span>
          {children && <div style={{ marginLeft: 20 }}>{children}</div>}
        </div>
      )}
    />
  );
}

Advanced Usage

Parent-Child Relationships

When your data has parent-child relationships (like a flat array with parentId fields):

interface TreeNode {
  id: number;
  name: string;
  parentId?: number;
}

const flatData: TreeNode[] = [
  { id: 1, name: "Root" },
  { id: 2, name: "Child 1", parentId: 1 },
  { id: 3, name: "Child 2", parentId: 1 },
  { id: 4, name: "Grandchild", parentId: 2 },
];

function TreeComponent() {
  const rootNodes = flatData.filter((node) => !node.parentId);

  return (
    <ElementsRenderer
      elements={rootNodes}
      getElementKey={(node) => node.id}
      getChildElements={(node) =>
        flatData.filter((child) => child.parentId === node.id)
      }
      renderElement={({ element, children, index }) => (
        <div style={{ paddingLeft: index * 20 }}>
          <div>{element.name}</div>
          {children}
        </div>
      )}
    />
  );
}

File System Tree

interface FileNode {
  name: string;
  type: "file" | "folder";
  children?: FileNode[];
}

const fileSystem: FileNode[] = [
  {
    name: "src",
    type: "folder",
    children: [
      {
        name: "components",
        type: "folder",
        children: [
          { name: "Button.tsx", type: "file" },
          { name: "Input.tsx", type: "file" },
        ],
      },
      {
        name: "utils",
        type: "folder",
        children: [{ name: "helpers.ts", type: "file" }],
      },
      { name: "App.tsx", type: "file" },
    ],
  },
];

function FileExplorer() {
  return (
    <ElementsRenderer
      elements={fileSystem}
      getElementKey={(node, index) => `${node.name}-${index}`}
      getChildElements={(node) => node.children}
      renderElement={({ element, children }) => (
        <div>
          <div
            style={{
              fontWeight: element.type === "folder" ? "bold" : "normal",
              color: element.type === "folder" ? "#0066cc" : "#333",
            }}
          >
            {element.type === "folder" ? "📁" : "📄"} {element.name}
          </div>
          {children && (
            <div
              style={{
                marginLeft: 20,
                borderLeft: "1px solid #ccc",
                paddingLeft: 10,
              }}
            >
              {children}
            </div>
          )}
        </div>
      )}
    />
  );
}

API Reference

ElementsRenderer Props

Prop Type Required Description
elements T[] Array of elements to render
getElementKey (element: T, index: number) => string | number Function to generate unique keys for React reconciliation
renderElement (props: RenderElementProps<T>) => ReactNode Function to render each element
getChildElements (element: T) => T[] | undefined Function to get child elements for recursion

RenderElementProps<T>

The renderElement function receives an object with these properties:

Property Type Description
element T The current element being rendered
childElements T[] | undefined Array of child elements (if any)
children ReactNode Pre-rendered children components
index number Index of the current element in its parent's children array

Use Cases

This component is perfect for:

  • 🌳 Navigation Menus: Multi-level dropdown menus
  • 📁 File Explorers: Folder/file tree structures
  • 🏢 Organizational Charts: Company hierarchy visualization
  • 📋 Category Lists: Nested product categories
  • 🗂️ Taxonomy Trees: Tag/category hierarchies
  • 📊 Decision Trees: Flowchart-like structures
  • 🎯 Sitemap Visualization: Website structure display

TypeScript Support

This package is built with TypeScript and provides full type safety:

interface MyElement {
  id: string;
  name: string;
  children?: MyElement[];
}

// TypeScript will infer the correct types
<ElementsRenderer<MyElement>
  elements={myElements}
  getElementKey={(element) => element.id} // element is typed as MyElement
  renderElement={(
    { element, children } // element is typed as MyElement
  ) => (
    <div>
      {element.name}
      {children}
    </div>
  )}
  getChildElements={(element) => element.children} // element is typed as MyElement
/>;

Performance Considerations

  • The component uses React keys for efficient reconciliation
  • Child elements are only rendered when they exist
  • Recursive rendering is optimized with React.Fragment
  • No unnecessary re-renders thanks to proper key management

License

MIT

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Support

If you find this package useful, please consider:

  • ⭐ Starring the repository
  • 🐛 Reporting bugs
  • 💡 Suggesting new features
  • 📖 Improving documentation