我是React和javascript的新手,所以请原谅我
我正在构建一个基本的todolist应用程序
Main App.js是以下
class App extends Component {
constructor(props) {
super(props);
this.fetchTasks = this.fetchTasks.bind(this)
this.strikeUnstrike = this.strikeUnstrike.bind(this)
};
state = {
todoList: [],
activeItem: {
id: null,
title: '',
completed: false,
},
editing: false,
}
componentDidMount() {
this.fetchTasks()
}
// pull the list of tasks from the API
fetchTasks() {
axios.get('http://127.0.0.1:8000/api/task-list/')
.then( response => {
this.setState({ todoList: response.data })
} )
}
strikeUnstrike(task) {
task.completed = !task.completed
let url = `http://127.0.0.1:8000/api/task-update/${task.id}/`
let data = {'completed': task.completed, 'title':task.title}
axios.post( url, data)
.then(response => this.fetchTasks() )
}
render() {
return (
<div className='container'>
<div id ='task-container'>
<TaskList
tasks = {this.state.todoList}
taptask = {this.strikeUnstrike(task)}
// taptask = {() => this.strikeUnstrike(task)} // also tried this
/>
</div>
</div>
)
}
}
export default App;
我的TaskList.js组件如下所示
import React from 'react';
const tasklist = (props) => {
return (
<div id='list-wrapper'>
{props.tasks.map((task, index) => {
// console.log('the task X is :', task) // works
// console.log('the passed prop is :', props.taptask) //works
return (
<div key={index} className="task-wrapper flex-wrapper">
<div onClick={props.taptask(task)} style={{flex:7}} >
{ task.completed == false ? (
<span>{task.title}</span>
) : (
<strike>{task.title}</strike>)}
</div>
<div style={{flex:1}}>
<button
// onClick={ props.editClick(task)}
className="btn btn-sm btn-outline-info">Edit</button>
{console.log('working')}
</div>
<div style={{flex:1}}>
<button
// onClick = {props.deleteClick(task)}
className="btn btn-sm btn-outline-dark">-</button>
</div>
</div>
)
})}
</div>
)
}
export default tasklist;
然而,我得到以下错误
TypeError: Cannot read property 'completed' of undefined
App.strikeUnstrike
src/frontend/src/App.js:134
131 | // this basically allows you to check off an item as complete by clicking on it
132 | // strikeUnstrike = (task) => {
133 | strikeUnstrike(task) {
> 134 | task.completed = !task.completed
| ^ 135 | console.log('TASK :' , task.completed)
136 |
137 | let csrfoken = this.getCookie('csrftoken')
View compiled
taptask
src/frontend/src/App.js:166
163 |
164 | <TaskList
165 | tasks = {this.state.todoList}
> 166 | taptask = {() => this.strikeUnstrike()}
| ^ 167 | // taptask = {this.strikeUnstrike(task)}
168 | // editClick = {()=> this.startEdit(task)}
169 | // deleteClick = {()=> this.deleteItem(task)}
View compiled
(anonymous function)
src/frontend/src/Components/TaskList/TaskList.js:15
12 | <div key={index} className="task-wrapper flex-wrapper">
13 |
14 |
> 15 | <div onClick={props.taptask(task)} style={{flex:7}} >
| ^ 16 |
17 | { task.completed == false ? (
18 | <span>{task.title}</span>
View compiled
我知道绑定,我已经尝试了几种方法(在构造函数和箭头函数方法中使用this. functionname .bind(this)),但我无法解决这个问题。如有任何帮助,不胜感激。
第一个选项是事先调用函数。第二个选项是传递一个函数,该函数使用了一个不存在的task
变量。
你传递一个函数给TaskList
,你应该直接传递这个函数,或者把它定义为一个箭头函数,你应该定义task
参数:
<TaskList
tasks = {this.state.todoList}
taptask = {this.strikeUnstrike} // this is better
taptask = {(task) => this.strikeUnstrike(task)} // this also works
/>
编辑正如@Nadia Chibrikova指出你的TaskList
,你也应该正确地修复你的onClick:
onClick={() => props.taptask(task)}
问题是,你的task
是undefined
。因此,您可以检查undefined
并正确处理它,这将防止脏错误。
133 | strikeUnstrike(task) {
> 134 | task.completed = task && !task.completed
让我们找出为什么task
是undefined
<TaskList
...
/** this will not work, because the function is executed
immediately instead of beeing passed down as props. **/
taptask = {this.strikeUnstrike(task)}
//instead use this
taptask = {this.strikeUnstrike}
//or this
taptask = {(task) => this.strikeUnstrike(task)} // pay attention to task, which is passed down to strikeUnstrike()
/>
请更改这一行:
taptask = {this.strikeUnstrike(task)}
:
taptask = {this.strikeUnstrike}
你需要给函数引用,你不需要调用它