Async content

Often the tree has a big structure and it is not good to load immediately the whole tree items. The library has only 2 ways to load a data from a server, but this is quite enough for any, even the most complex requirements. See below for more details on each of them.

Data initializing

Note that there is no data initialization parameter or something like that. Only data property. Let's examine how is elementary to load a data from the server.

import React from 'react'
import EyzyTree from 'eyzy-tree'
import AwesomeLoadingIndicator from 'awesome-loading-indicator'
import 'eyzy-tree/style.css'

export default LazyTree extends React.Component {
    // https://babeljs.io/docs/en/babel-plugin-proposal-class-properties
    // instead you can use constructor :)
    state = {
        treeData: [],
        isDataLoaded: false
    }

    componentDidMount() {
        fetch('/awesome_API/v1/?tree')
            .then(response => response.json())
            .then(data => {
                this.setState({
                    isDataLoaded: true,
                    treeData: data
                })
            })
    }
    
    render() {
        if (!this.state.isDataLoaded) {
            return <AwesomeLoadingIndicator />
        }
        
        return (
            <EyzyTree data={this.state.treeData} />
        )
    }
}

Node's property

Each node of a tree might has a isBatch property. The tree perceives this property as: node has children and it should be received from the server (see fetchData property). It will show an arrow and an user is able to expand the node. Class loading will be added to the node. And upon completion, the class will be removed and new nodes will be added as children to this node.

Example of component data:

const treeData = [
    { text: 'Item 1' },
    { text: 'Item 2' },
    { text: 'Item 3' },
    { text: 'Item 4', isBatch: true } // this node will has a "expandable" arrow
]

// This method must return a Promise
function handleFetchData(node) {
    // Note that it is important to return a valid JS object (not `fetch` response)
    return fetch(`/api?nodeText=${node.text}`)
        .then(response => response.json())

    // or you can use a library for the request
    return axios.get('/user', {
        params: {
            nodeText: node.text
        }
    })
}

// component example
<EyzyTree 
    data={treeData}
    fetchData={handleFetchData}
/>

Using API

There are several methods that allow you to add new nodes as children asynchronously.

  • append (see API)

  • prepend (see API)

I see no reason to re-describe how the methods work (you can look at the link above). Better I will show a simple and real example.

import React from 'react'
import EyzyTree from 'eyzy-tree'
import axios from 'axios'
import 'eyzy-tree/style.css'

export default LazyTree extends React.Component {
    treeApi = null

    constructor(props) {
        super(props)

        this.state = {
            data: [
                'Item 1',
                'Item 2',
                'Item 3',
                'Item 4',
                'Item 5',
            ]
        }
    }

    loadNode = (node) => {
        return axios.get('/awesome_API/v1/tree', {
            params: {
                nodeText: node.text
            }
        })
    }

    handleTreeReady = (api) => {
        this.treeApi = api
    }

    handleClick = () => {
        this.treeApi.append({ selected: true }, this.loadNode)
    }

    render() {
        return (
            <div className="tree">
                <EyzyTree 
                    data={this.state.treeData}
                    onReady={this.handleTreeReady}
                />
            </div>
            <div className="controls">
                <button onClick={this.handleClick}>Add to Selected</button>
            </div>        
        )
    }
}

Insertion options

There are few options:

  • expand whether to expand node

  • loading whether to show loading indicator

  • index insertion index

const options = {
    expand: true,
    loading: false
}

this.api.append(/item/, (node) => {
    return axios.get('/awesome_API/v1/tree', {
        params: {
            nodeText: node.text
        }
    })
}, options)

Last updated