1

I am new to React and javascript so please bear with me

I am building a basic todolist app

Main App.js is the following

  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;

My TaskList.js component looks like the following

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;

Yet, I'm getting the following error

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

I am aware of bindings and I've tried several approaches (using this.functionName.bind(this) in the constructor and the arrow function approach) however I'm not able to resolve the issue. Any help would be much appreciated.

0

3 Answers 3

1

First option you are invoking a function before hand. Second option you are passing a function that uses a task variable that it doesn't exist.

you are passing down a function to TaskList, for that you should pass the function directly, or define it as arrow function you should define the task parameter:

      <TaskList
        tasks = {this.state.todoList}
        taptask = {this.strikeUnstrike} // this is better
        taptask = {(task) => this.strikeUnstrike(task)} // this also works
      />  

Edit as @Nadia Chibrikova points at your TaskList you should also fix your onClick correctly:

onClick={() => props.taptask(task)}
Sign up to request clarification or add additional context in comments.

1 Comment

I'd add onClick={props.taptask(task)} should be onClick={() =>props.taptask(task)}
0

The issue here is, that your task is undefined. So you could check for undefined and handle it properly, that would prevent the dirty error.

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

Then let's find out why task is 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()
      />    

Comments

0

Please change this line:

    taptask = {this.strikeUnstrike(task)}

to this:

    taptask = {this.strikeUnstrike}

You need to give function reference, you don't need to call it.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.