RyaanH
1
I am passing the deleteTask(task) function to the child to remove task from state on button click in child
import React from 'react'
import ToDoListItemRow from '../components/ToDoListItemRow.js'
import '../styles/todolist.css'
class ToDoList extends React.Component {
constructor(props) {
super(props)
this.state = {
tasks: ['run', 'eat', 'code', 'sleep'],
input: ''
}
this.handleSubmit = this.handleSubmit.bind(this)
this.handleChange = this.handleChange.bind(this)
this.deleteTask = this.deleteTask.bind(this)
}
handleSubmit(e) {
e.preventDefault()
this.setState({
tasks: [...this.state.tasks, this.state.input],
input: ''
})
}
handleChange(e) {
this.setState({
input: e.target.value
})
}
deleteTask(task) {
console.log("this is working")
this.setState({
tasks: this.state.tasks.slice(0, task).concat(this.state.tasks.slice(task + 1, this.state.tasks.length))
})
}
render() {
const tasks = this.state.tasks.map((item, id) => {
return <ToDoListItemRow key={id} task={item} func={this.deleteTask}/>
})
return(
<div>
<form onSubmit={this.handleSubmit} className="form">
<input value={this.state.input} onChange={this.handleChange} type='text' placeholder='What is your task?' className="input-field"/>
<button type='submit' className="form-submit">Add Task</button>
</form>
<ul className="todolist">
{tasks}
</ul>
</div>
)
}
}
export default ToDoList
This is the child and i use deleteTask(task) in the onClick function
import React from 'react'
import '../styles/todolist.css'
class ToDoListItemRow extends React.Component {
constructor(props) {
super(props)
}
render() {
return(
<div className="todolist-row">
<li className="task">{this.props.task}</li>
<button type="button" className="button-delete" onClick={this.props.func(this.props.task)}>Delete</button>
</div>
)
}
}
export default ToDoListItemRow
I am trying to delete a task from an array inside the parent’s state so the child gets deleted when re-rendering but it causes an infinite loop.
Here is the error.
can you provide a link to your project ?
RyaanH
3
its local is there any way I can upload to show online?
can you provide a screen shot of the parent and child classes (complete one)
if you want to use any function of parent on child you need to pass it as a prop.
RyaanH
5
I updated the screenshots to the full classes. I did pass the parent function as prop in the mapping.
You need to render the ToDoListItemRow inside the parent class with the required props and function.
<ToDoListItemRow task={#} func={#} />
RyaanH
8
I do in the tasks mapping just above the return statement, I then place {tasks} in the ul
const tasks = this.state.tasks.map((item, id) => {
return <ToDoListItemRow key={id} task={item} func={this.deleteTask}/>
})
return(
<div>
<form onSubmit={this.handleSubmit} className="form">
<input value={this.state.input} onChange={this.handleChange} type='text' placeholder='What is your task?' className="input-field"/>
<button type='submit' className="form-submit">Add Task</button>
</form>
<ul className="todolist">
{tasks}
</ul>
</div>
)
}
RyaanH
10
I fixed the code, passing an argument causes the infinite loop and I have no idea why.
RyaanH
11
Everything works but the delete function.
Your onclick function needs the function name as the value. You should not call it…
In order to call the function with an argument you need to declare another function that calls the func() with argument;
function <funcName> {
func(task);
}
<button type="button" className="button-delete" onClick={this.<funcName>}>Delete</button>
RyaanH
13
nope still loops :(. Good try though! I actually though that was going to work. I am posting the error I get so you can see.
RyaanH
14
returning e.target.value deletes the task at the beginning of the array, how can i make it so it deletes the this.props.task value from the array?
render() {
return(
<div className="todolist-row">
<li className="task">{this.props.task}</li>
<button type="button" className="button-delete" onClick={(e) => this.props.deleteTask(e.target.value)}>Delete</button>
</div>
)
}
class ToDoListItemRow extends React.Component {
constructor(props) {
super(props)
this.delFunc = this.delFunc.bind(this);
}
delFunc() {
this.props.func(this.props.i);
}
render() {
return(
<div className="todolist-row">
<li className="task">{this.props.task}</li>
<button type="button" className="button-delete" onClick={this.delFunc}>Delete</button>
</div>
)
}
}
deleteTask(task) {
console.log("this is working")
console.log(this.state.tasks);
this.setState((prevState) => ({
tasks: prevState.tasks.filter((item, i) => {
return i !== task;
})
}));
}
render() {
let tasks = this.state.tasks.map((item, id) => {
return <ToDoListItemRow key={id} i={id} task={item} func={this.deleteTask}/>
})
return(
<div>
<form onSubmit={this.handleSubmit} className="form">
<input value={this.state.input} onChange={this.handleChange} type='text' placeholder='What is your task?' className="input-field"/>
<button type='submit' className="form-submit">Add Task</button>
</form>
<ul className="todolist">
{tasks}
</ul>
</div>
)
}
}
RyaanH
18
Amazing my friend. How does a task !== i, if i is a number?
RyaanH
19
and why couldn’t we just send key back instead of i?
both are numbers here…
return <ToDoListItemRow key={id} i={id} task={item} func={this.deleteTask}/>
here i passed ‘i’ as a prop to indicate the index of the corresponding task in array.
this.props.func(this.props.i);
in here i passed that index as argumet for the task to delete.
and finally compared the index in the array matching to the item to be deleted.
tasks: prevState.tasks.filter((item, i) => {
return i !== task;
})
1 Like
RyaanH
21
why couldn’t you just pass the key and filter out the one that matches the key?
coz the key prop is used under the hood by the react comp. It is not exposed for manipulation. if you use ‘this.props.key’ it returns undefined.
1 Like