reactjscrudreact-contextuse-reducer

Iam making a Todo using (useReducer and useContext) but the update functionality is not working please check this out


This is my App.jsx , where iam displaying all the todos, after clicking edit the input gets the value of selected todo and while changing the value and clicking on update it does nothing.

export default function App() {
  const { dispatch, state } = useContext(todoContext);
  const [todo, setTodo] = useState("");
  const [isEditing, setIsEditing] = useState(false);
  const [selectedTodo, setSelectedTodo] = useState("");

  const handleSubmit = (e) => {
    const id = uuidv4();
    e.preventDefault();

    if (!isEditing) {
      dispatch({
        type: "ADD_TODO",
        payload: { id: id, text: todo },
      });
      setTodo("");
    } else {
      dispatch({
        type: "UPDATE_TODO",
        payload: selectedTodo,
      });
      setIsEditing(false);
      setTodo("");
    }
  };

  const handleEdit = (val) => {
    setIsEditing(true);
    const item = state.todos.find((todo) => todo.id === val.id);
    setTodo(item.text);
    setSelectedTodo(item);
  };

  return (
    <div className="App">
      <br />
      <h1>Hello World This is Todo App</h1>
      <br />

      <form onSubmit={handleSubmit}>
        <input
          value={todo}
          onChange={(e) => setTodo(e.target.value)}
          type="text"
          placeholder="Enter a todo"
        />
        <button>{isEditing ? "Update" : "Submit"}</button>
      </form>

      {state.todos.map((item) => (
        <div key={item.id} className="todoitem">
          <p
            onClick={() => dispatch({ type: "TOGGLE_TODO", payload: item.id })}
            style={{
              cursor: "pointer",
              textDecoration: item.completed ? "line-through" : "",
            }}
          >
            {item.text}
          </p>
          <span
            onClick={() => dispatch({ type: "REMOVE_TODO", payload: item.id })}
          >
            &times;
          </span>
          <button onClick={() => handleEdit(item)}>Edit</button>
        </div>
      ))}
    </div>
  );
}

This is my reducers (todoReducer.jsx) , where the upadte functionality doesnot work when i click edit to change the value and click update it does nothing

export const INITIAL_STATE = {
  todos: [],
  updated: [],
};

export const reducer = (state, action) => {
  switch (action.type) {
    case "ADD_TODO":
      return {
        ...state,
        todos: [...state.todos, action.payload],
      };
    case "REMOVE_TODO": {
      return {
        ...state,
        todos: state.todos.filter((item) => item.id !== action.payload),
      };
    }
    case "TOGGLE_TODO":
      return {
        ...state,
        todos: state.todos.map((todo) =>
          todo.id === action.payload
            ? { ...todo, completed: !todo.completed }
            : todo
        ),
      };
    case "UPDATE_TODO":
      return {
        ...state,
        todos: state.todos.map((todo) => {
          if (todo.id === action.payload.id) {
            return action.payload;
          }
          return todo;
        }),
      };
    default:
      return state;
  }
};

Solution

  • you need to update text with latest text

    in your handleSubmit please update below code

          dispatch({
            type: "UPDATE_TODO",
            payload: { ...selectedTodo, text: todo },
          });