Reputation: 457
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
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