Recursive Data Lister
React component that recursively pretty prints nested lists or objects with various options for html markup and styling.
Features
- Quickly display simple or complex nested lists and objects as html.
- Choice of html (ul, ol, div, etc.).
- Display as a single list or separate lists per first level parent.
- For arrays of objects, the option to choose a property to use its value as the heading (replace the numerical index).
- Handles dates. Either provide a formatter function, or by default will be displayed as strings. Also attempts to find and handle dates in string values.
- Basic default CSS available with easy customization through cssVars prop.
Demo
https://npm-library-demo.vercel.app/recursive-data-lister
Install
- npm
- Yarn
- pnpm
npm install @unleashit/recursive-data-lister
yarn add @unleashit/recursive-data-lister
pnpm add @unleashit/recursive-data-lister
Example
import React from 'react';
import RecursiveDataLister from '@unleashit/recursive-data-lister';
const users = [
{
id: 1,
name: 'joe',
booksRead: [
{
title: 'The Castle',
author: 'Franz Kafka',
},
{
title: 'Waynes World 2',
author: 'Mike Meyers IV',
},
],
},
{
id: 2,
name: 'judy',
booksRead: [
{
title: 'The Overcoat',
author: 'Nikolai Gogol',
editions: ['first: 1842', 'second: 1844'],
},
],
},
];
const RecursiveDataListerDemo = () => (
<RecursiveDataLister
data={users}
multiList={true} // For top level array only: show first level children as separate lists. False is default (outputs as a single top level html list)
tag="ul" // parent html tag. ul is default, you can also choose ol or div
arrayBranchProp="title" // if set, this will use the property as node labels for arrays of objects (instead of the index). Careful with this, it only works with one property!
removeRepeatedProp={true} // false is default. If arrayBranchProp is set, this will remove the prop from the object so it isn't repeated
/>
);
export default RecursiveDataListerDemo;
CSS
By default, all components come with basic css styling in two formats: standard (BEM namespaced) and a CSS Module friendly version.
To use the standard version, import it like: import '@unleashit/recursive-data lister/dist/recursive-data lister.css'
. Or if you are using CSS Modules you can import css from '@unleashit/recursive-data lister/dist/recursive-data lister.module.css'
and provide to the cssModule
prop and/or use your own custom module targeting the internal class names.
See styling-and-theming for more info.
CSS Custom Properties
You can get pretty far without having to write any custom CSS. By supplying a cssVars
prop, you can override any of the CSS variables of the default css.
See styling-and-theming for more info.
API
RecursiveDataListerProps
Props for Recursive Data Lister.
export interface RecursiveDataListerProps {
/** Array or object of data to display */
data: Record<string, any> | any[];
/** Top level html tag for the list, like ul, ol or div */
tag?: keyof JSX.IntrinsicElements;
/**
* Display in multiple ul, ol, etc. lists per parent
* Data must be an array
*/
multiList?: boolean;
/**
* When a branch is an array of objects, select an object property to be used as a label instead
* of the index. Note: this is a global setting, and applies to all child arrays
* If the key isn't found, the index will be used anyway
*/
arrayBranchProp?: string | null;
/** By default, the arrayBranchProp will be repeated in the list */
removeRepeatedProp?: boolean;
/**
* Detect ISO 8601 date strings and convert into Date objects
* for the purpose of formatting with the dateFormat prop.
* Uses the parseISO function from date-fns
*/
handleISOStringDates?: boolean;
/**
* Function to customize the printed output of date objects
* The default is toString()
*/
dateFormat?: DateFormat;
/** CSS custom property overrides */
cssVars?: CSSVars<typeof varNames>;
/** CSS module to target internal styles */
cssModule?: Record<string, string>;
}
DateFormat
Function to format date objects. Should return a string or number of the formatted date. Note: the component attempts to find and transform stringified dates into date objects. These will then also be passed to this function if available.
export type DateFormat = (val: Date) => string | number;
Name | Type | Description | default |
---|---|---|---|
data | object or array | object to display | required |
multilist | boolean | For array only: show first level children as separate parents | false |
tag | string | Parent HTML tag for a choice of ordered/unordered list or plain divs | ul |
arrayBranchProp | string | if set, it will use the property as branch labels for arrays of objects (instead of the index) | null |
removeRepeatedProp | boolean | If arrayBranchProp is set, this will remove the prop from the array so it isn't repeated | false |
dateFormat | function | Callback to process Date objects or strings, receives the Date or Date like string | (elem) => elem.toString() |
cssVars | object | optional object to override css custom properties | undefined |
cssModule | object | CSS Module object that optionally replaces default. Class names need to match expected names. | undefined |