0

I'm trying to implement a remove function to hierarchical components. With it being app.jsx > notes.jsx > note.jsx. And this is just making a simple to-do list that im following from a tutorial. I've loaded it with babel and have a hard time understanding why this deletes the whole todo list rather than just a single list element.

App.jsx :

import React from 'react';
import Note from './Note';
import Notes from './Notes';

export default class App extends React.Component {
    constructor(props) {
    super(props);

    this.state = {
      notes: [{
        task: 'Learn webpacks'
      }, {
        task: 'Learn React'
      }, {
        task: 'Do laundry'
      }]
    };
  }


    render() {
        var notes = this.state.notes;
        return (
          <div>
            <button onClick= {()=>this.addItem()}> + </button>
            <Notes items = {notes}
            onEdit = {(i, task) => this.itemEdited(i, task)} 
            removeItem = {(i) => this.removeItem(i)} 
             />

            </div>
            );  
    }

    itemEdited(i, task) {
    var notes = this.state.notes;

    if(task) {
      notes[i].task = task;
    }
    else {
      notes = notes.slice(0, i).concat(notes.slice(i + 1));
    }

    this.setState({
      notes: notes
    });
  }


    addItem() {
        this.setState({
        notes : this.state.notes.concat([{
            task : 'New Task'
        }])

        });
    }

    removeItem(i) {
    var notes = this.state.notes;
    this.setState({
        notes : this.state.notes.slice(0, i)
    });
    }
}

Notes.jsx

import React from 'react';
import Note from './Note';

export default class Notes extends React.Component {
    render() {
        var notes = this.props.items;

        return(
        <ul className='notes'>{notes.map((note, i) =>
            <li className = 'note' key = {'note' + i}>
                <Note value = {note.task}
                 onEdit = {this.props.onEdit.bind(null, i)}
                 removeItem = {this.props.removeItem.bind(null, i)}
                 /> 


            </li>
            )}</ul>
        );
    }
}

Note.jsx

import React from 'react';

export default class Note extends React.Component {

    constructor(props) {
        super(props);

        this.state = {
        edited: false
        };
    }

    render() {
        const {value, onEdit, ...props} = this.props;
        var edited = this.state.edited;

            return (
                <div {...props}> {
                    edited
                    ? <input type = 'text'
                      defaultValue = {value}
                      onBlur = {(e) => this.finishEdit(e)}
                      onKeyPress={(e) => this.checkEnter(e)}/>
                    : <div onClick={() => this.edit()}> {value} </div>
                }
                <button onClick = {(i) => this.props.removeItem(i
            )}>-</button>  
                </div>

            );
        }

        edit() {
        this.setState({edited: true});
        }

        checkEnter(e) {
        if(e.key === 'Enter') {
          this.finishEdit(e);
            }
        }

        finishEdit(e) {
        this.props.onEdit(e.target.value);
        this.setState({edited:false});
        }



}

Everything works fine but removing a single list element, instead of deleting the element it deletes the whole list. I think it has to do with the logic of passing down removeItem, but I don't know exactly what has to be passed down. The way I see it, note is the individual note/list element so in order to remove it the function would have to trickle down this class correct?

Edited: with attempt of how i think it should work.

2
  • this.props.removeItem.bind(i) is missing a null - you are binding to the index and therefor not passing in anything as an argument which causes the slice to go to the end. Commented Jul 13, 2015 at 17:42
  • Ahh thanks for the heads up, I found the problem and your comment lead me back to the root Commented Jul 13, 2015 at 17:54

1 Answer 1

2

What had went wrong was 1: was not binding null to this.props.removeItem.bind(i)

Secondly I was slicing the whole thing when what I intended to do was splice it, instead I just did it like this:

removeItem(i) {
    var notes = this.state.notes;
    notes = notes.slice(0, i).concat(notes.slice(i + 1));
    this.setState({
        notes : notes
    });
    }

take all the elements before that list and concatenate it with everything after. Although notes = notes.splice(i, 1) should also work correct? I tried it, but it would remove everything but that element.

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

1 Comment

if you don't mind using tools like underscore / lodash, you can do something like this: notes = _.without(notes, _.findWhere(notes, {id: 1}));

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.