【问题标题】:function scope error in React. Cannot read property of undefinedReact 中的函数范围错误。无法读取未定义的属性
【发布时间】:2021-05-17 05:08:39
【问题描述】:

我是 React 和 javascript 的新手,所以请多多包涵

我正在构建一个基本的 todolist 应用程序

主要的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) 和箭头函数方法)但是我无法解决问题。任何帮助将不胜感激。

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    第一个选项是您事先调用一个函数。第二个选项是传递一个使用不存在的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)}
    

    【讨论】:

    • 我要添加 onClick={props.taptask(task)} 应该是 onClick={() =&gt;props.taptask(task)}
    【解决方案2】:

    这里的问题是,您的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()
          />    
    

    【讨论】:

      【解决方案3】:

      请更改此行:

          taptask = {this.strikeUnstrike(task)}
      

      到这里:

          taptask = {this.strikeUnstrike}
      

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-10-22
        • 2020-11-21
        • 2018-06-24
        • 2023-02-20
        • 1970-01-01
        • 1970-01-01
        • 2022-01-16
        相关资源
        最近更新 更多