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.
this.props.removeItem.bind(i)is missing anull- you are binding to the index and therefor not passing in anything as an argument which causes the slice to go to the end.