Alice
Alice

Reputation: 331

Pass map's argument to function in ReactJS

I am trying to make a todoList by ReactJS. I want to delete an item by its id, but when I console.log(id), it returns undefined. Here is my code

App.js:

import React, { Component } from 'react';
import './App.css';

import Header from './Components/header';
import InputTodo from './Components/todoInput';

class App extends Component {
  constructor(props){
    super(props);
    this.state={
      todos:[
        {id:0,text:'Make dinner'},
        {id:1,text:'Fold the laundary'},
        {id:2,text:'Do homework'}
      ]
    }
  }

  addHere=(text)=>{
    this.setState({
      todos:this.state.todos.concat([text])
    })
  }

  removeHere=(id)=>{
    console.log(id);
    // let arr=this.state.todos;
    // let index=arr.findIndex((x)=>x.id===id);
    // console.log(index);
  }
  render() {
    return (
      <div className='todo-wrapper'>
        <Header/>
        <InputTodo todoText='Type Here...' addTodo={this.addHere}/>
        <div>
          {this.state.todos.map((value,key)=>{
            return (
            <div className='row myList' key={key}>
            <p className='col-xs-10'> {value.text}-{value.id} </p>
            <button className='btn btn-danger pull-right col-xs-2' onClick={this.removeHere(value.id)}>Delete</button> 
            </div>
          )})}
        </div>
      </div>
    );
  }
}

export default App;

The following is InputTodo.js:

import React, {Component} from 'react';
import '../App.css';

export default class InputTodo extends Component{
    constructor(props){
        super(props);
        this.state={
            todoInput:{
                id:2,
                text:''
            }
        }
    }


    handleSubmit=(e)=>{
        if(this.refs.title.value===''){
            alert('You must input something');
        }
        else{
            this.state.todoInput={
                id:this.state.todoInput.id+1,
                text:this.refs.title.value
            };
            this.setState(this.state);
            this.props.addTodo(this.state.todoInput);
            this.refs.title.value='';
        }
        e.preventDefault();

    }
    render(){
        return(
            <form className='input-group' onSubmit={this.handleSubmit}>
                <input type='text' ref="title" className='form-control'placeholder={this.props.todoText}/>
                <span className='input-group-btn'>
                <input type='submit' value='Submit' className='btn btn-primary'  />
                </span>
            </form>
        );
    }
}

Upvotes: 0

Views: 104

Answers (1)

Channing Allen
Channing Allen

Reputation: 98

While FuzzyTree's answer will work, a cleaner approach would be extracting the todo item's JSX into its own component. This would have the added benefit of not creating a new function for the button's onClick prop every time App's render function gets called.

The component might look like this:

// TodoItem

class TodoItem extends Component {
  handleRemove = () => this.props.onRemove(this.props.id)

  render() {
    return (
      <div className='row myList'>
        <p className='col-xs-10'> {this.props.text}-{this.props.id} </p>
        <button className='btn btn-danger pull-right col-xs-2' onClick={this.handleRemove}> Delete </button>
      </div>
    )
  }
}

// App render

  render() {
    return (
      <div className='todo-wrapper'>
        <Header/>
        <InputTodo todoText='Type Here...' addTodo={this.addHere}/>
        <div>
          {this.state.todos.map(({ id, text }, key) =>
            <TodoItem key={key} id={id} text={text} onRemove={this.removeHere} />
          )}
        </div>
      </div>
    );
  }

Upvotes: 1

Related Questions