EDIT : Solution found. I forgot to had a prop 'handleCallback' when creating my subList
renderSubList() {
let subList = this.props.item.subList
if (subList === undefined)
return
subList = subList.map(
item =>
<Item key={item.id} item={item} handleCallback={...} /> <== HERE
)
return subList
}
I'm a bit new with Reactjs so I'm trying to do a custom TODO list with task and subtask. I'm facing a problem when I want to delete a subtask telling me that my callback isn't a function. I have no issue when deleting a task. I don't really understand my problem, is it a callback problem or maybe my data structure?
P.S: this is my first post, it is a bit ugly.
github repo for the code : https://github.com/JohnPAfr/todolist
So my data looks like this:
todoList:[
{id:0, task:'tâche #1', subList: [
{id:0, parent:0, task:'sous-tâche #1'},
{id:1, parent:0, task:'sous-tâche #2'},
{id:2, parent:0, task:'sous-tâche #3'},
]},
{id:1, task:'tâche #2'},
{id:2, task:'tâche #3'},
{id:3, task:'tâche #4'},
]
My problem comes when I want to delete an item from the subList.
I map my 'todoList' from my state and make a TodoItem for each object in my list.
class TodoBis extends Component {
constructor(props){
super(props)
this.state = {
todoList: ... (see above)
}
this.renderTodoItems = this.renderTodoItems.bind(this)
this.handleAdding = this.handleAdding.bind(this)
this.handleDelete = this.handleDelete.bind(this)
}
renderTodoItems() {
let list = this.state.todoList
list = list.map(
item =>
<TodoItem key={item.id} item={item} handleDelete={this.handleDelete}/>
)
return list
}
handleAdding(input) {...}
handleDelete(item) {...}
render() {
return (
<div>
<AddBar handleAdding={this.handleAdding} />
{this.renderTodoItems()}
</div>
);
}
}
TodoItem create an item with subitems
class TodoItem extends Component {
constructor(props) {
super(props)
this.renderSubList = this.renderSubList.bind(this)
this.handleCallback = this.handleCallback.bind(this)
}
renderSubList() {
let subList = this.props.item.subList
if (subList === undefined)
return
subList = subList.map(
item =>
<Item key={item.id} item={item} />
)
return subList
}
handleCallback(item) {
this.props.handleDelete(item)
}
render() {
const {item} = this.props
return (
<div>
<Item key={item.id} item={item} handleCallback={() => this.props.handleDelete(item)} />
<div className={(item.subList === undefined) ? '' : 'subList'}>
{this.renderSubList()}
</div>
</div>
);
}
}
Finally I have Item which displays my data
class Item extends Component {
render() {
const {item} = this.props
const task = item.task
return (
<div onClick={() => this.props.handleCallback(this.props.item)} className='item-container'>
<span>{task}</span>
</div>
)
}
}
I expect to delete the correct task or subtask when Item is clicked.
This code confuses me:
handleCallback() {
const handleCallback = this.props.handleCallback
const item = this.props.item
console.log(item)
handleCallback(item)
}
<div onClick={() => this.handleCallback(item)} className='item-container'>
<span>{task}</span>
</div>
Why don't you change it to this:
<div onClick={() => this.props.handleCallback(this.props.item)} className='item-container'>
<span>{task}</span>
</div>
The second handleCallback is not needed, it does no additional logic.