# 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.

```jsx
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 ](https://eyzy.gitbook.io/tree/component-props#options)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:

```jsx
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](https://eyzy.gitbook.io/tree/api/basic#append))
* prepend (see [API](https://eyzy.gitbook.io/tree/api/basic#prepend))

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.

```jsx
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

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

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