Skip to main content
1 of 2

A simple todo list in ReactJS

I have a working useless todo app created with ReactJS. I'm just wondering if my code can be improved.

This app can add a todo item and it can display editable list of todo items.

This is my ReactJS code.

var TodoApp = React.createClass({
    getInitialState: function() {
        return {items: []};
    },
    addItem: function(item) {
        var allItems = this.state.items.concat([item]);
        this.updateItems(allItems);
    },
    editItem: function(editedItem) {
        var allItems = this.state.items.map(function(item) {
            if (item.id !== editedItem.id) {
                return item;
            }

            return editedItem;
        });

        this.updateItems(allItems);
    },
    updateItems: function(items) {
        this.setState({items: items});
    },
    render: function() {
        return (
            <div className="todo-app">
                <TodoForm onFormSubmit={this.addItem}/>
                <TodoList items={this.state.items} onItemEdit={this.editItem}/>
            </div>
        );
    }
});

var TodoForm = React.createClass({
    getInitialState: function() {
        return {item: {id: 0, title: '', description: ''}};
    },
    render: function() {
        return (
            <form onSubmit={this.handleSubmit}>
                <input type="hidden" ref="id" value={this.state.item.id} onChange={this.handleUserInput}/>
                <input type="text" ref="title" value={this.state.item.title} onChange={this.handleUserInput}/>
                <input type="text" ref="description" value={this.state.item.description} onChange={this.handleUserInput}/>
                <input type="submit" value="Add"/>
            </form>
        );
    },
    handleSubmit: function(e) {
        e.preventDefault();

        this.props.onFormSubmit(this.state.item);
        this.setState({item: {id: 0, title: '', description: '', done: false}});
    },
    handleUserInput: function() {
        this.setState({item: {
            id: this.refs.id.value,
            title: this.refs.title.value,
            description: this.refs.description.value,
            done: false
        }});
    }
});

var TodoList = React.createClass({
    render: function() {
        var component = this;

        var itemNodes = this.props.items.map(function(item) {
            return <TodoListItem key={item.title} item={item} onFormSubmit={component.props.onItemEdit}/>
        });

        return (
            <ul>{itemNodes}</ul>
        );
    }
});

var TodoListItem = React.createClass({
    getInitialState: function() {
        return {
            id: this.props.item.id,
            done: this.props.item.done,
            title: this.props.item.title,
            description: this.props.item.description,
        };
    },
    render: function() {
        return (
            <li>
                <form onSubmit={this.handleFormSubmit}>
                    <input type="hidden" ref="id" value={this.state.id}/>
                    <input type="checkbox" ref="done" value={this.state.done} onChange={this.handleUserInput}/>
                    <input type="text" ref="title" value={this.state.title} onChange={this.handleUserInput}/>
                    <input type="text" ref="description" value={this.state.description} onChange={this.handleUserInput}/>
                    <input type="submit" value="Save"/>
                </form>
            </li>
        );
    },
    handleUserInput: function() {
        this.setState({
            id: this.refs.id.value,
            done: this.refs.done.checked,
            title: this.refs.title.value,
            description: this.refs.description.value
        });
    },
    handleFormSubmit: function(e) {
        e.preventDefault();
        this.props.onFormSubmit(this.state);
    }
});

ReactDOM.render(<TodoApp/>, document.getElementById('todoListBox'));

ReactJS said in their docs that components should be stateless as possible. I'm aware that in the TodoListItem component, It has a state based from its props. I did that so I can change the form inside TodoListItem.

Is there any other possible solutions to do this other than their two way binding add-on?