2
\$\begingroup\$

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?

200_success
145k22 gold badges190 silver badges478 bronze badges
asked Dec 11, 2015 at 8:47
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

So I managed to eliminate the TodoListItem's state, which is based on its props, by reusing the TodoForm component with a minor tweak for an inline form.

This is the TodoListItem and TodoForm component now.

var TodoForm = React.createClass({
 getInitialState: function() {
 return {item: {
 id: this.props.todoId,
 title: this.props.todoTitle,
 description: this.props.todoDescription,
 done: this.props.todoDone
 },
 isAnInlineForm: this.props.isAnInlineForm};
 },
 render: function() {
 return (
 <form onSubmit={this.handleSubmit}>
 <input type="checkbox" ref="done" checked={this.state.item.done} onChange={this.handleUserInput}/>
 <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="Save"/>
 </form>
 );
 },
 handleSubmit: function(e) {
 e.preventDefault();
 this.props.onFormSubmit(this.state.item);
 if (!this.state.isAnInlineForm) {
 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: this.refs.done.checked
 }});
 }
});
var TodoListItem = React.createClass({
 render: function() {
 return (
 <li>
 <TodoForm onFormSubmit={this.handleFormSubmit}
 todoId={this.props.item.id}
 todoDone={this.props.item.done}
 todoTitle={this.props.item.title}
 todoDescription={this.props.item.description}
 isAnInlineForm={true}
 />
 </li>
 );
 },
 handleFormSubmit: function(item) {
 this.props.onFormSubmit(item);
 }
});
answered Dec 14, 2015 at 6:04
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.