Reputation: 9
Below is my Types file
type InputType = {
one: string;
two: string;
};
type ToDoType = {
id: number,
name: string,
complete: boolean
};
type ToDoAction = {
type: string;
payload: {
name: string;
};
};
type ToDoArray = ToDoType[];
const ACTIONS = {
//const because it holds as our object of actions
ADD_TODO: "add-todo",
TOGGLE_TODO: "toggle-todo",
DELETE_TODO: "delete-todo",
};
I am receiving the error below. It is highlighted within the useReducer hook on the established reducer parameter itself... also receiving an error within my dispatch but i figured the root problem is within the useReducer function itself
No overload matches this call. Overload 1 of 5, '(reducer: ReducerWithoutAction, initializerArg: ToDoArray, initializer?: undefined): [ToDoArray, DispatchWithoutAction]', gave the following error. Argument of type '(todos: ToDoArray, action: ToDoAction) => ToDoArray | undefined' is not assignable to parameter of type 'ReducerWithoutAction'. Overload 2 of 5, '(reducer: ReducerWithoutAction, initialState: ToDoArray, initializer?: undefined): [ToDoArray, Dispatch]', gave the following error. Argument of type '(todos: ToDoArray, action: ToDoAction) => ToDoArray | undefined' is not assignable to parameter of type 'ReducerWithoutAction'.ts(2769)
import * as React from "react";
import { useState, useReducer, useEffect } from "react";
import Todo from "./components/Todo";
import "./App.css";
import './components/Types'
function reducer(todos: ToDoArray, action: ToDoAction): ToDoArray | undefined{
switch (action.type) {
case ACTIONS.ADD_TODO:
return [...todos, newToDo(action.payload.name)];
}
}
function newToDo(name: string): ToDoType {
return { id: Date.now(), name: name, complete: false };
}
function App() {
const [todos, dispatch] = useReducer<React.ReducerWithoutAction<ToDoArray>>(reducer, [] as ToDoArray);
const [userInput, setUserInput] = useState<InputType>({
one: "",
two: "",
} as InputType);
useEffect(() => {
setTimeout((e: React.ChangeEvent<HTMLInputElement> ) => {
setUserInput({ one: e.currentTarget.value, two: "" })
}, 5000)
}, [userInput.one])
//UPDATES STATE onKEYSTROKE
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setUserInput({ one: e.currentTarget.value, two: "" });
};
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
dispatch({ type: ACTIONS.ADD_TODO, payload: { name: userInput.one } });
setUserInput({ one: "", two: "" });
};
return (
<>
<div className="App h-screen bg-red-400 flex justify-center items-center flex-col gap-8">
<p
className="title
text-5xl
first-letter:font-bold
first-letter:text-white
tracking-widest
first-letter: ml-2
"
>
TO-DO LIST
</p>
<form onSubmit={handleSubmit} className="">
<input
onChange={handleChange}
id="xxx"
type="text"
value={userInput.one}
className="
input
w-72
rounded-sm
shadow-xl
border-none
outline-none
p-1"
/>
</form>
{todos.map((todo: ToDoType) => {
<Todo id={todo.id} todo={todo} dispatch={dispatch} />;
})}
</div>
</>
);
}
export default App;
Upvotes: 0
Views: 61
Reputation: 145
Copy the following solution :
type ReducerFn = (todos: ToDoArray, action: ToDoAction) => ToDoArray;
function reducer(todos: ToDoArray, action: ToDoAction): ToDoArray {
switch (action.type) {
case ACTIONS.ADD_TODO:
return [...todos, newToDo(action.payload.name)];
default: {
return [];
}
}
}
and change the useReducer
line to -
const [todos, dispatch] = useReducer<ReducerFn>(reducer, []);
and also the todos.map
to
{todos.map((todo: ToDoType) => (
<Todo id={todo.id} todo={todo} dispatch={dispatch} />
))}
Upvotes: 0