在React中函数作用域错误.无法读取未定义的属性



我是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)}

问题是,你的taskundefined。因此,您可以检查undefined并正确处理它,这将防止脏错误。

133 | strikeUnstrike(task) {
> 134 |   task.completed = task && !task.completed

让我们找出为什么taskundefined

<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}

你需要给函数引用,你不需要调用它

最新更新