Skip to content
Filatov Dmitry edited this page Feb 24, 2018 · 29 revisions

Let's create a simple application which represents a sorted list of users with ability to add and remove users from it.

First of all we need to figure out how to decompose our application to the components. We'll use the following structure:

App
|-- UserList
|   `-- UserListItem
`-- NewUser

Then let's import required parts from vidom module.

import { Component, mount } from 'vidom';

App

Our top component App is a stateful component which will be responsible for the maintenance of the state of our application: a list of users represented by a regular array. In turn each user is a plain object with id and login fields. We'll support two operations: adding a new user and removing existing one.

class App extends Component {
    // store empty array as initial list of users
    onInit() {
        this.setState({ users : [] });
    }

    // onRender() hook is called when the component needs to be rendered. 
    onRender() {
        const { users } = this.state;

        return (
            <div class="app">
                <NewUser onAdd={ login => this.onAddUser(login) }/>
                <UserList list={ users } onRemove={ id => this.onRemoveUser(id) }/>
            </div>
        );
    }

    onAddUser(login) {
        // Just adding a new user to the array and resorting it.
        this.setState({
            users : this.state.users
                .concat({ id : generateId(), login })
                .sort((a, b) => a.login > b.login)
        });
    }

    onRemoveUser(id) {
        // Just removing a user from the array using "id".
        this.setState({
            users : this.state.users.filter(item => item.id !== id)
        });
    }
}

In onAddUser we're using generateId() function so let's define it:

let counter = 0;
function generateId() {
    return counter++;
}

UserList

The next component UserList is very simple, it just renders wrapping <ul> and creates corresponding nodes for each user.

class UserList extends Component {
    onRender() {
        const { list, onRemove } = this.attrs;

        return (
            <ul>
                {
                    list.map(user =>
                        <UserListItem
                            key={ user.id }
                            user={ user }
                            onRemove={ onRemove }
                        />
                    )
                }
            </ul>
        );
    }
}

UserListItem

UserListItem renders user's login and button to remove user from the list by click.

class UserListItem extends Component {
    onRender() {
        const { user, onRemove } = this.attrs;

        return (
            <li>
                <span>{ user.login }</span>
                <button onClick={ () => onRemove(user.id) }>remove</button>
            </li>
        );
    }
}

NewUser

class NewUser extends Component {
    onInit() {
        this.setState({ login : '' });
    }

    onRender() {
        const { login } = this.state;

        return (
            <input
                placeholder="enter new login"
                value={ login }
                onChange={ e => this.onInputChange(e) }
                onKeyUp={ e => this.onInputKeyUp(e) }
            />
        );
    }

    onInputChange(e) {
        this.setState({ login : e.target.value });
    }

    onInputKeyUp(e) {
        if(e.nativeEvent.keyCode === 13) {
            const value = e.target.value.trim();

            if(value) {
                this.setState({ login : '' });
                this.attrs.onAdd(value);
            }
        }
    }
}

And the final touch — mounting our application to the DOM:

mount(document.body, <App/>);