React checkbox local storage

I am building a To-Do List web app with React as my first project.

I want to implement local storage which works fine only that,I am unable to handle check and uncheck of the checkbox prefectly.

Here is a link to the deployed website so you can understand the problem I am having.

https://rapture-todo.netlify.app/

When you add a todo, and mark it complete.

on reload, the checkbox of the todo is unchecked but the todo is marked complete.

Here is my source code[github link- https://github.com/coolpythoncodes/React-ToDo-List].

For App.js

import React, { Component } from 'react';

import Header from './component/Header';
import Info from './component/Info';
import AddToDo from './component/AddToDo';
import TodoListItem from './component/TodoListItem';

import './sass/main.scss';


class App extends Component{
  constructor(props){
    super(props);

    this.state= {
      value: '',
      list: [],
      show: true,
    };

    this.handleChange= this.handleChange.bind(this);
    this.handleSubmit= this.handleSubmit.bind(this);
    this.handleInputChange = this.handleInputChange.bind(this);
    this.deleteTask = this.deleteTask.bind(this);
  }

  componentDidMount() {
    const list = window.localStorage.getItem('userTodo') ? JSON.parse(localStorage.getItem('userTodo')) : [];
    this.setState({ list })
}

  handleChange(e) {
    this.setState({value:e.target.value})
  }

// Handle submission of user todo item
  handleSubmit(e) {
    e.preventDefault();
    const newTask = {
      id: Date.now(),
      userTodo: this.state.value,
      isCompleted: false,
      checked: false,
    }
    
    // Validate form so user doesn't add an empty to do
    if (this.state.value.length > 0) {
      this.setState({
        list: [newTask, ...this.state.list],
        value: '', // Clear input field
        show: true, // Success message
      }, ()=>{
        window.localStorage.setItem('userTodo', JSON.stringify(this.state.list));
      })
    }

  }
  
  // Handles checkbox
  handleInputChange(id) {
    this.setState({list: this.state.list.map(item => {
      if (item.id === id) {
        item.isCompleted = !item.isCompleted; 
        item.checked = !this.state.checked;
    }return item
    })}, ()=>{
      window.localStorage.setItem('userTodo', JSON.stringify(this.state.list));
    })

  }

  // Delete a task
  deleteTask(id){
    this.setState({list: this.state.list.filter(item => item.id !== id )},()=>{
      window.localStorage.setItem('userTodo', JSON.stringify(this.state.list))
    })
    console.log(this.state.list)
  }

  

  render(){
    return(

        <div>
          <Header />
          <Info />
          <AddToDo onChange={this.handleChange} value={this.state.value} onSubmit={this.handleSubmit} />
          <TodoListItem deleteTask={this.deleteTask} onChange={this.handleInputChange} list={this.state.list} defaultChecked={this.state.checked} />
        </div>

    )
  }
}

export default App;

For TodoListItem.js

import React, { Component } from 'react';
import ToDoItem from './ToDoItem';

import '../sass/main.scss';

class ToDoListItem extends Component{

  render(){
    const {list, onChange, deleteTask, defaultChecked} = this.props;
    return(
        <div>
            {list.map((todo)=>{
                return (
                    <ToDoItem 
                        key={todo.id}
                        userTodo={todo.userTodo} 
                        isCompleted={todo.isCompleted}
                        onChange={onChange}
                        id={todo.id}
                        deleteTask={deleteTask}
                        defaultChecked={defaultChecked}
                    />
                )
            })}

        </div>
    )
  }
}


export default ToDoListItem;

For TodoItem.js

import React, { Component } from 'react';

import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faTrashAlt } from '@fortawesome/free-solid-svg-icons'


import '../sass/main.scss';

class ToDoItem extends Component{

  render(){
    const {userTodo, isCompleted, onChange, id, deleteTask, defaultChecked} = this.props;
    const checkStyle =  isCompleted ? 'completed-todo' : 'not-completed-todo';
    return(
        
      <div className={`container  ${checkStyle}`}>
            <input type="checkbox" onChange={onChange.bind(this, id)} defaultChecked={defaultChecked}/>
            <div >
                <p className='title'>{userTodo}</p>
            </div>

            {/* Delete button */}
            <button onClick={deleteTask.bind(this, id)}><FontAwesomeIcon className='remove-icon' icon={faTrashAlt} /></button>
            

      </div>
    )
  }
}


export default ToDoItem;

Please note: I have gone through other questions similar to the problem I am having but I could not solve this problem.

If I did not state the question well, please let me know.

Upvotes: 0

Views: 1330

Answers (1)

sidthesloth
sidthesloth

Reputation: 1467

In the below code in App.js,

<TodoListItem deleteTask={this.deleteTask} onChange={this.handleInputChange} list={this.state.list} defaultChecked={this.state.checked} />

You are setting, defaultChecked={this.state.checked} Why do you do that? There is nothing called checked in the state.

In fact, there is no need to pass the defaultValue.

Make the following changes,

  1. In App.js, remove defaultValue prop for TodoListItem
<TodoListItem deleteTask={this.deleteTask} onChange={this.handleInputChange} list={this.state.list}/>
  1. In TodoListItem.js, remove defaultChecked={defaultChecked}
<ToDoItem
              key={todo.id}
              userTodo={todo.userTodo}
              isCompleted={todo.isCompleted}
              onChange={onChange}
              id={todo.id}
              deleteTask={deleteTask}
              defaultChecked={defaultChecked} // Remove this.
            />
  1. In ToDoItem.js,
<input type="checkbox"onChange={onChange.bind(this, id)}
  defaultChecked={isCompleted} // Replace defaultValue with isCompleted
/>

Upvotes: 1

Related Questions