eskimopest
eskimopest

Reputation: 457

React typescript useReducer issues

I'm learning react and typescript. I'm trying to build a todo app with useReducer but im getting some errors. Don't know if they are connected or not.

My code is the following

import { useReducer, useState } from "react";
import { Sidebar } from "../components/Sidebar";

interface State {
  todos: [];
}

enum ActionType {
  Add = "ADD",
  Remove = "REMOVE",
}

interface Action {
  type: ActionType;
  payload: {
    id: string;
    title: string;
  };
}

const initialState: State = {
  todos: [],
};

const reducer = (state: State, action: Action) => {
  switch (action.type) {
    case ActionType.Add:
      return [
        ...state.todos,
        { id: action.payload.id, title: action.payload.title },
      ];
    case ActionType.Remove:
      
    default:
      return state.todos;
  }
};
export const Todo = () => {
  const [state, dispatch] = useReducer(reducer, initialState);   // first mistake is here
  const [input, setInput] = useState<string>("");

  const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    // second mistake is here
    dispatch({
      type: ActionType.Add,
      payload: { id: crypto.randomUUID(), title: input },
    });
  };

  return (
    <>
      <Sidebar />
      <div className="main">
        <form onSubmit={(e) => handleSubmit(e)}>
          <input type="text" onChange={(e) => setInput(e.target.value)} />
          <button>add</button>
        </form>
      </div>
    </>
  );
};

first mistake is : useReducer says "No overload matches this call..."

second is when i call dispatch it says "Expected 0 arguments, but got 1"

thanks in advance for the help.

Upvotes: 0

Views: 22

Answers (1)

Ori Drori
Ori Drori

Reputation: 192607

Your state is an object, with a single property - todos, which should be an array of Todo items. The reducer is supposed to take the original state, and return a new state (or the same state) with the same shape. When you're adding an item, or at the default type you only return the array of todos. In addition, the payload is a todo item, but the todos is just an array without item type.

See comments in code (TS playground):

interface Todo {
  id: string;
  title: string;
}

interface State {
  todos: Todo[];
}

enum ActionType {
  Add = "ADD",
  Remove = "REMOVE",
}

interface Action {
  type: ActionType;
  payload: Todo; // The payload is a Todo
}

const initialState: State = {
  todos: [],
};

const reducer = (state: State, action: Action) => {
  switch (action.type) {
    case ActionType.Add:
      // return the same shape of state
      return {
        todos: [
          ...state.todos,
          {
            id: action.payload.id,
            title: action.payload.title
          },
        ]
      }
    case ActionType.Remove:

    default:
      return state; // return the entire state and not just todos
  }
};

Upvotes: 0

Related Questions