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-tree-renderer

v2.0.8

Published

A recursive render component for react | react的递归渲染组件

Downloads

37

Readme

react-tree-renderer

A tree render component for react | react的树状渲染组件

I want some component to render a tree without considering how to nest them, just provide the Template for One tree node. So come this project

我希望在React中渲染一个任意的树形结构,而不需要去考虑如何去嵌套每个层级,只需要提供一个根节点的数据和一个渲染模板

With this you can easily customise a treeview, a json editor, or anything tree alike

通过这个树形结构渲染工具,你可以轻松实现一个treeview(层级菜单、文件夹结构等)或者JSON编辑器等

screenshot watch on youtube https://youtu.be/P011GNWfDvs

在线体验 | try online: https://postor.github.io/react-tree-renderer/ codes: examples\basic\pages

usage | 使用

install | 安装

npm install react-tree-renderer --save

# or | 或

yarn add react-tree-renderer

code

<TreeRenderer Template={Template} data={root} />

data

object with data look like self in children nodes | children包含和自身类似结构的对象

{
  title: 'root',
  children: [
    {
      title: 'test1',
    }
  ]
}

Template

Component to show one node | 用于显示一个节点的组件

props ready for use in Template explained in comments | Template可以使用的 props 在注释中描述

const Template = (props) => {
    // props ready for use in Template | Template可以使用的 props 
    const { 
      data = {},  // data for current node | 当前节点的数据
      children = [], // rendered children | 渲染后的子节点
      deleteMe, // function to delete this node | 删除本节点的函数
      addChildren // add children to this node | 批量添加下级节点的函数
      isRoot, // tell if this node is root | 判断此节点是否为 root
      i, // index of current node in sblings, root got undefined | 在同辈中的顺序索引,根节点为 undefined
      updateData, // function to update this node's data | 更新本节点数据的函数
      treeEvent, // function to trigger an event | 发起事件的函数
      updateParent, // function to update parent node's data | 更新父节点数据的函数
    } = props
    return (
        <div>
            <p>{data.title}</p>
            <ul>
                {children.map((x, i) => (<li key={i}>{x}</li>))}
            </ul>
        </div>
    )
}

simply show | 简单显示

for details go to examples/basic

import TreeRenderer from 'react-tree-renderer'

//data, use children to nest nodes | 要展示的数据,使用children属性来嵌套数据
const root = {
    title: 'root',
    children: [
        {
            title: 'test1',
            children: [
                {
                    title: 'test2',
                    children: [
                        {
                            title: 'test3',
                        },
                        {
                            title: 'test4',
                        }
                    ],
                },

            ],
        },
    ],
}

//template for one node | 对应一个节点的渲染模板
const Template = (props) => {
    //data from props, data is a node from the root, children is the templated views of data.children
    //从props获取data,data为root中的一个节点,children则是对应data.children经过模板转换的视图列表
    const { data = {}, children = [], } = props
    return (
        <div>
            <p>{data.title}</p>
            <ul>
                {children.map((x, i) => (<li key={i}>{x}</li>))}
            </ul>
        </div>
    )
}

//as a tree | 渲染整个树状结构
export default (props)=>(
  <TreeRenderer Template={Template} data={root} />
)

example screenshot

with data updating | 同时需要更新数据

in this example, you can modify the titles and add new nodes | 在这个例子中,演示了修改每个节点的title和增加新节点

import React from 'react'
import TreeRenderer from 'react-tree-renderer'

class DefaultTemplate extends React.Component {

  render() {
    const { data = {}, children = [], addChildren, updateData, deleteMe, isRoot } = this.props

    return (
      <div>
        <input value={data.title} onChange={e => updateData({
          ...data,
          title: e.target.value,
        })} />
        {!isRoot && <button onClick={() => deleteMe()}>x</button>}
        <ul>
          {children.map((x, i) => (<li key={i}>{x}</li>))}
        </ul>
        <button onClick={() => addChildren([{ title: 'newly added' }])}>+</button>
      </div>
    )
  }
}

export default class TestTree extends React.Component {
  constructor(props, ctx) {
    super(props, ctx)
    this.state = {
      root: {
        title: 'root',
        children: [
          {
            title: 'test1',
          }
        ]
      }
    }
  }

  render() {
    const { root = {} } = this.state

    //pass onUpdateData to TreeRenderer to handle data change | 给TreeRenderer传递onUpdateData来处理数据变化
    return (<TreeRenderer Template={DefaultTemplate} data={root} onUpdateData={(root) => this.setState({ root, })} />)
  }
}

example screenshot

with event | 使用事件

sometimes we have more things to do besides updating data of the corresponding node, but parent or sibling or the whole tree, then you can use event

有时候你不止需要更新对应节点的数据,可能是上层的同级别的或者整个树,这时候你可以用event

Template

import React from 'react'

//define your own events | 自定义事件类型
export const eventTypes = {
  closeAll: 'closeAll',
  openAll: 'openAll'
}

export default class DefaultTemplate extends React.Component {

  handleOpen(isOpen) {
    const { data = {}, updateData, } = this.props
    updateData({
      ...data,
      isOpen,
    })
  }

  handleOpenAll(isOpen) {
    //use treeEvent from props to fire an event | 使用props中的treeEvent来触发一个事件
    const { treeEvent } = this.props
    treeEvent(isOpen ? eventTypes.openAll : eventTypes.closeAll)
  }

  render() {
    const { data = {}, children = [], } = this.props
    const handleOpen = this.handleOpen.bind(this)
    const handleOpenAll = this.handleOpenAll.bind(this)

    const getControls = (isOpen) => {
      if (isOpen) {
        return (<em><span onClick={() => handleOpen(false)}>close</span> <span onClick={() => handleOpenAll(false)}>close all</span></em>)
      }
      return (<em><span onClick={() => handleOpen(true)}>open</span> <span onClick={() => handleOpenAll(true)}>open all</span></em>)
    }

    return (
      <div>
        <p>{data.title} {getControls(data.isOpen)}</p>
        <ul style={{ display:data.isOpen?'block':'none'}}>
          {children.map((x, i) => (<li key={i}>{x}</li>))}
        </ul>
      </div>
    )
  }
}

container

import React from 'react'

import { default as TreeRenderer, pathGet, pathMerge } from 'react-tree-renderer'
import { default as DefaultTemplate, eventTypes } from './DefaultTemplate'

export default class TestTree extends React.Component {

  constructor(props, ctx) {
    super(props, ctx)
    this.state = {
      root: {
        title: 'root',
        children: [
          {
            title: 'test1',
            children: [
              {
                title: 'test11',
              },
              {
                title: 'test12', children: [
                  {
                    title: 'test1',
                    children: [
                      {
                        title: 'test11',
                      },
                      {
                        title: 'test12',
                      }
                    ],
                  },
                  {
                    title: 'test2',
                  }
                ],
              }
            ],
          },
          {
            title: 'test2',
          }
        ],
      }
    }
  }

  onUpdateData(root) {
    this.setState(
      { root, }
    )
  }

  onTreeEvent(eventStr, eventData, path) {
    const { root = {} } = this.state
    const obj = pathGet(root, path)

    const setOpenRecursive = (isOpen, obj) => {
      const { children = [] } = obj
      return {
        ...obj,
        isOpen,
        children: children.map(x => setOpenRecursive(isOpen, x))
      }
    }
    const updateState = (newObj) => {
      const newRoot = pathMerge(root, path, newObj)
      this.setState({
        root: newRoot,
      })
    }

    switch (eventStr) {
      case eventTypes.closeAll:
        updateState(setOpenRecursive(false, obj))
        break;
      case eventTypes.openAll:
        updateState(setOpenRecursive(true, obj))
        break;
      default:
        break;
    }
  }


  render() {
    const onUpdateData = this.onUpdateData.bind(this)
    const onTreeEvent = this.onTreeEvent.bind(this)
    const { root = {} } = this.state

    //pass onTreeEvent handle to TreeRenderer | 给TreeRenderer传递处理函数onTreeEvent
    return (<TreeRenderer Template={DefaultTemplate} data={root} onUpdateData={onUpdateData} onTreeEvent={onTreeEvent} />)
  }
}

example screenshot