how to use two useState in one function so that the second useState can use the first updated useState?

Viewed 143

REACT: I am trying to create todoapp and I have a problem with the component responsible for adding a new task. I would like to assign an add date to a new task. Here is my component (tasksList is a list of all tasks) :

import { useState } from "react";

const ListHandler = ({ tasksList, setTasksList }) => {

  const [newTask, setNewTask] = useState({
    id: tasksList.length,
    content: "",
    done: false,
    active: true,
    date: null,
  });

  const inputHandler = (e) => {
    setNewTask((prevState) => ({
      ...prevState,
      content: e.target.value,
    }));
  };

  const addHandler = (e) => {
    e.preventDefault();
    setNewTask((prevState) => ({
      ...prevState,
      date: new Date().toTimeString().split(" ")[0],
    }));
    setTasksList((prevState) => [...prevState, newTask]);
  };

  return (
    <section className="listHandler">
      <form className="form">
        <input
          className="form__input"
          onChange={(e) => inputHandler(e)}
        ></input>
        <button className="form__button" onClick={(e) => addHandler(e)}>
          Add Task
        </button>
      </form>
    </section>
  );
};
export default ListHandler;

when I click the button, I get a new task in the tasksList with a null date because setTasksList is called before updating the newTask, right? My question is how to fix this?

2 Answers

This Might Solve Your Problem Created a new state TaskName for handling change input and fixed addhandler function and inputhandler.

  const [newTask, setNewTask] = useState([]);
  const [taskName, setTaskName] = useState("");


    const inputHandler = (e) => {
      setTaskName(e.target.value);
    };
    const addHandler = (e) => {
      e.preventDefault();
      setNewTask([...newTask,{
        id: newTask.length+1,
        content: taskName,
        done: false,
        active: true,
        date: new Date().toTimeString().split(" ")[0],
      }]);
      setTaskName("");
    };

That happened because the newTask will be available in the next render, you can do this for example:

    const addHandler = (e) => {
        e.preventDefault();
        const newDate = date: new Date().toTimeString().split(" ")[0];
        
        setNewTask((prevState) => ({
          ...prevState,
          date: newDate
        }));
       
        setTasksList((prevState) => [...prevState, {...newTask, date: newDate }]);
      };
Related