How to update property state without using this

I'm updating one of my state properties without using the setter and using a normal variable assignment in js, that causes me the problem that the property state only updates once, so when i want to check a checkbox more than once the state in app does not update correctly, i think that the problem causing it is that i'm messing up that property assignment.

I searched for how to update a property of a state without overwritting the whole object and every post i find answering that question is using this.setState instead of declaring a state and using the declared setter method and i don't know how to adapt that this update to my code.

For example, the top post called "How to update nested state properties in React" declares his state like this:

this.state = {
   someProperty: {
      flag:true
   }
}

While i'm declaring my state like this:

const [EditedTask, setEditedTask] = useState({
    name: props.task.name,
    completed: props.task.completed,
    _id: props.task._id,
  });

  const { name, completed } = EditedTask;

And the top answer to that question is:

this.setState(prevState => ({
    ...prevState,
    someProperty: {
        ...prevState.someProperty,
        someOtherProperty: {
            ...prevState.someProperty.someOtherProperty, 
            anotherProperty: {
               ...prevState.someProperty.someOtherProperty.anotherProperty,
               flag: false
            }
        }
    }
}))

In this solution, with which object should i replace the this in the this.setState? Or the prevState param?

In my code i need to update the checkbox/ completed state, with this solution i'm only receiving the object EditedTask in my app component when i edit the checkbox once, if i check it more than once the state doesn't update in app, meanwhile if i edit the name the state updates in app correctly with both the name and completed propertys.

import React, { useState } from "react";
import "../App.css";

const EditTask = (props) => {
  const [EditedTask, setEditedTask] = useState({
    name: props.task.name,
    completed: props.task.completed,
    _id: props.task._id,
  });

  const { name, completed } = EditedTask;

  const onChange = (e) => {
    setEditedTask({
      ...EditedTask,
      [e.target.name]: e.target.value,
    });
  };

  const onSubmit = (e) => {
    e.preventDefault();
    setEditedTask(EditedTask);
    props.saveEditedTask(EditedTask);
    props.changeEdit(false);
  };

  return (
    <>
      <form onSubmit={onSubmit}>
        <div className="form-group">
          <label>Task Id: ${props.task._id}</label>
          <div className="inputEdit">
            <input
              type="text"
              placeholder={props.msg}
              name="name"
              onChange={onChange}
              value={name}
            />
          </div>
        </div>
        <div className="form-check">
          <input
            className="form-check-input"
            type="checkbox"
            defaultChecked={completed}
            value={completed}
            onChange={() => (EditedTask.completed = !EditedTask.completed)}
            name="completed"
          />
          <label className="form-check-label">Completed</label>
        </div>
        <div className="submit">
          <button type="submit">Edit</button>
        </div>
      </form>
    </>
  );
};

export default EditTask;

I tried replacing the onChange={() => (EditedTask.completed = !EditedTask.completed)} like the top answer/ my onChange for the name value with something like this but it doesn't update the completed value

const updateCompleted = (e) => {
    setEditedTask({
      ...EditedTask,
      [e.target.name]: !e.target.value,
    });
  };

Solution 1:

You can try something like this in your setter functions.

const updateCompleted = (e) => {
 setEditedTask((currentState) => ({
   ...currentState,
   [e.target.name]: !e.target.value
   })
)};

This solution will give you your previous state, which your can use to update your state.