'Edit todo list in axios with ReactJS

I just started learn reactjs and axios. I have problem with my update method please do help. I am trying to update the item in the same input field. The item is not getting updated instead adding as a new item. I think there is also problem with button click but I am not understanding how to solve the issue. I hope some one will help me.

import React, { Component } from "react";
import { Input, Button, Form } from "reactstrap";
import axios from "axios";
import { baseUrl } from "./baseUrl";

class Reference extends Component {
  constructor(props) {
    super(props);
    this.state = {
      itemsList: [],
      inputData: "",
    };
    this.handleOnChange = this.handleOnChange.bind(this);
    this.addItem = this.addItem.bind(this);
    this.deleteItem = this.deleteItem.bind(this);
    this.getItem = this.getItem.bind(this);
    this.updateItem = this.updateItem.bind(this);
    
  }

  handleOnChange(event) {
    this.setState({
      inputData: event.currentTarget.value,
    });
    event.preventDefault();
  }

  getItem() {
    try {
      axios.get(baseUrl).then((response) => {
        console.log(response.data);
        this.setState({
          itemsList: response.data,
        });
        console.log(this.state.itemsList);
      });
    } catch (err) {
      console.log(err);
    }
  }

  componentDidMount() {
    this.getItem();
  }

  addItem(event) {
    event.preventDefault();
    if (this.state.inputData !== "") {
      try {
        axios.post(baseUrl, { title: this.state.inputData }).then((res) => {
          console.log(this.state.inputData);
          this.setState({
            inputData: ''
          })
          this.getItem();
        });
      } catch (err) {
        console.log(err);
      }
    }
  }

  deleteItem(id) {
    try {
      axios.delete(`http://localhost:3001/data/${id}`).then((res) => {
        this.state.itemsList.filter((Item) => Item.id !== id);
        this.getItem();
      });
    } catch (err) {
      console.log(err);
    }
  }

  updateItem(id, val) {
    try {
      axios
        .put(`http://localhost:3001/data/${id}`, { title: val })
        .then((res) => {
          this.state.itemsList.filter((Item) => Item.id !== id);
          this.setState({
          inputData:val,
        });
        });
    } catch (err) {
      console.log(err);
    }
  }
  

  render() {
    return (
      <div className="Todo">
          <Form id="todo-list" onSubmit={this.addItem} className="m-1">
            <Input
              type="text"
              name="name"
              value={this.state.inputData}
              placeholder="Add Item"
              onChange={this.handleOnChange}
            ></Input>
            <Button
              type="button"
              className="m-2"
              color="primary"
            >
              Add
            </Button>
          </Form>
            {this.state.itemsList.map((todo) => (
                <div key={todo.id} className="card">
                <div className="container">
                  <p>
                    {todo.title}
                    <div>
                      <button
                        className="fa fa-trash fa-lg"
                        onClick={() => this.deleteItem(todo.id)
                      }
                        
                      >
                        Delete
                      </button>
                      <button
                        className="fa fa-edit fa-lg"
                        onClick={() =>
                          this.updateItem(todo.id, todo.title)
                        }
                      >
                        Edit
                      </button>
                    </div>
                  </p>
                </div>
              </div>
            ))}
            </div>
            /*<li key={todo.id}>
                {todo.title}
                <span
                  className="fa fa-trash fa-lg"
                  onClick={() => {
                    this.deleteItem(todo.id);
                  }}
                ></span>
                <span
                  className="fa fa-edit fa-lg"
                  onClick={() => {
                    this.updateItem(todo.id, todo.title);
                    console.log(this.updateItem(todo.id, todo.title));
                  }}
                ></span>
              </li>
            ))}
          </ul>
        </div>
      </div>*/
    );
  }
}
export default Reference;


Solution 1:[1]

The issue is with the line

this.state.itemsList.filter((Item) => Item.id !== id);

React wont rerender if you directly mutate the state object. More reference can be read here https://daveceddia.com/why-not-modify-react-state-directly

You are using the filter method which returns a new array For example if you consider the list below

let list = [1,2,3,4]
let eventList = list.filter(num => num % 2 === 0)
console.log(evenList)
//[2,4]
Here a new list is created..

If you want to update a certain item in a list then you can use the .map method

let list = [1,5,3,4]
let doubleEven = list.map((num) => {
  if (num % 2 === 0 ) {
    return num * 2
  }

  return num // This is important as map method needs to return something in this case the number itself, else you will get undefined
})

// [1,5,3,8] Here we updated only the even number

Back to your code

updateItem(id, val) {
    try {
      axios
        .put(`http://localhost:3001/data/${id}`, { title: val })
        .then((res) => {
          this.setState({
          itemList: this.state.filter((Item) => {
             if(Item.id === id) {
               // Modify what ever
             } 

             return Item
          }),
          inputData:val,
        });
        });
    } catch (err) {
      console.log(err);
    }
  }

There are other ways to do this by passing a function to set state to modify state, but kept the solution simple

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Nitish Phanse