3

What would be the best way to render out the todos object when that object is updated? I've tried mapping through it, but it returns nothing with errors.

Code:

import React from 'react';
const Todo = React.createClass({

    getInitialState() {
        return ({todos: []})
    },

    newTodo(e) {
        let today = new Date();
        if (e.key === 'Enter') {
          console.log(this.state.todos)
          this.setState({
              todos: this.state.todos.concat({title: e.target.value, date: today})
          })
        }
    },

    delTodo(e) {},

    render() {
        return (
            <div className="panel panel-default">
                <div className="panel-heading">Todo List Creator</div>
                <div className="panel-body">
                    <input type="text" placeholder="enter todo name" className="form-control" onKeyPress={this.newTodo}/>
                </div>
                <ul className="list-group">
                    {this.state.todos.map((td, index) => {
                        <li key={index} className="list-group-item">
                            <strong>{td.name}</strong><br/>
                            {td.date}
                        </li>
                    })}
                </ul>
            </div>
        );
    }
});

export default Todo
3
  • can you show where you are using map to render the todo items ? Commented May 16, 2017 at 18:12
  • i guess that would have helped :D Commented May 16, 2017 at 18:15
  • i updated the code Commented May 16, 2017 at 18:18

2 Answers 2

5

You are not returning anything inside map body, with map if you don't return anything it will return undefined by default.

Use this:

<ul className="list-group"> 
    {this.state.todos.map((td, index) => { 
        return <li key={index} className="list-group-item"> 
                    <strong>{td.name}</strong>
                    <br/> 
                    {td.date.toDateString()} 
               </li> 
        }) 
    } 
</ul>

Or you can write it like this also without using the {}:

<ul className="list-group"> 
    {this.state.todos.map((td, index) => (
           <li key={index} className="list-group-item"> 
                 <strong>{td.name}</strong>
                 <br/> 
                 {td.date.toDateString()}
           </li> 
       )) 
    } 
</ul>

Note:

We can't render any object/array inside jsx directly, since date is an object so you need to convert that into string by using toDateString() or any other date method.

Check the working todo example:

const Todo = React.createClass({
    getInitialState() {
        return ({todos: []})
    },

    newTodo(e) {
        let today = new Date();
        if (e.key === 'Enter') {
          this.setState({
              todos: this.state.todos.concat({title: e.target.value, date: today})
          })
        }
    },

    delTodo(index) {
       let todos = this.state.todos.slice();
       todos.splice(index, 1);
       this.setState({todos})
    },

    render() {
        return (
            <div className="panel panel-default">
                <div className="panel-heading">Todo List Creator</div>
                <div className="panel-body">
                    <input type="text" placeholder="enter todo name" className="form-control" onKeyPress={this.newTodo}/>
                </div>
                <ul className="list-group"> 
                    {this.state.todos.map((td, index) => { 
                        return <li key={index} className="list-group-item"> 
                                  <strong>{td.title}</strong>  
                                  <button onClick={() => this.delTodo(index)}>delete</button>
                                  <br/> 
                                  {td.date.toDateString()} 
                               </li> 
                        }) 
                    } 
                </ul>
            </div>
        );
    }
});

ReactDOM.render(<Todo/>, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id='app'/>

Check this snippet for map:

let a = [1,2,3,4,5,6];

let b = a.map(el => {
   if(el % 2)
      return el;
});

console.log(b);

Sign up to request clarification or add additional context in comments.

4 Comments

when i use return i get the "Objects are not valid as a React child" error in the console.
reason is, you are rendering the date object directly inside jsx and we can't render object/array directly, convert that into string by using toDateString() or any other date method, use this: {td.date.toDateString()}
i need to be able to delete the todo now.
that was not ur ques :), check the updated answer with working todo app including delete functionality, run the snippet :)
0

If you want the arrow function to return a value use () instead of {}

{this.state.todos.map((td, index) => (
    <li key={index} className="list-group-item">
       <strong>{td.name}</strong><br/>
       {td.date}
    </li>
))

Comments

Your Answer

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.