I'm a beginner learning ts for the first time. Thank you in advance for sharing your knowledge. I am making a todolist. I used react to complete it. But now I am using react and typescript together to complete the code.
It seems to me that 'reducer' is not working properly. How can I operate this? I'd appreciate it if you let me know. This is 'App.tsx' code with surface error.
import React, { useState } from "react";
import Add from "./Add";
import List from "./List";
import ToDo from "./ToDo";
import Title from "./Title";
import Progress from "./Progress";
import styled from "styled-components";
interface ITodo {
toDos: string;
completed: boolean;
}
function App() {
const { toDos, completed } = useState<ITodo>(); Error part
return (
<Title>
<Add />
<Progress />
<Lists>
<List title={toDos.length !== 0 ? "To Dos" : ""}>
{toDos.map((toDo: any) => (
<ToDo key={toDo.id} id={toDo.id} text={toDo.text} isCompleted={false} />
))}
</List>
<List title={completed.length !== 0 ? "Completed" : ""}>
{completed.map((toDo: any) => (
<ToDo key={toDo.id} id={toDo.id} text
{...toDo.text} isCompleted />
))}
</List>
</Lists>
</Title>
);
}
export default App;
This code is the 'reducer.tsx' code that I thought there was a problem.
import { v4 as uuidv4 } from "uuid";
import { ADD, DEL, COMPLETE, UNCOMPLETE, EDIT } from "./actions";
export const initialState = {
toDos: [],
completed: [],
};
const reducer = ({ state, action }: any) => {
switch (action) {
case ADD:
return {
...state,
toDos: [...state.toDos, { text: action.payload, id: uuidv4() }],
};
case DEL:
return {
...state,
toDos: state.toDos.filter((toDo: { id: number; }) => toDo.id !== action.payload),
};
case COMPLETE:
const target = state.toDos.find((toDo: { id: number; }) => toDo.id === action.payload);
return {
...state,
toDos: state.toDos.filter((toDo: { id: number; }) => toDo.id !== action.payload),
completed: [...state.completed, { ...target }],
};
case UNCOMPLETE:
const aTarget = state.completed.find(
(toDo: { id: any; }) => toDo.id === action.payload
);
return {
...state,
toDos: [...state.toDos, { ...aTarget }],
completed: state.completed.filter(
(complete: { id: number; }) => complete.id !== action.payload
),
};
case EDIT:
const bTarget = state.toDos.find((toDo: { id: number; }) => toDo.id === action.id);
const rest = state.toDos.filter((toDo: { id: number; }) => toDo.id !== action.id);
return {
...state,
toDos: rest.concat({ ...bTarget, text: action.payload }),
};
default:
return;
}
};
export default reducer;
This code is 'context.tsx' code.
import React, { createContext, useReducer, useContext } from 'react';
import reducer, { initialState } from "./reducer";
export type Todo = {
id: number;
text: string;
done: boolean;
};
export type TodosState = Todo[];
const ToDosContext = createContext<TodosState | any>(undefined);
const ToDosProvider = ({ children }: { children: React.ReactNode }) => {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<ToDosContext.Provider value={{ state, dispatch }}>
{children}
</ToDosContext.Provider>
);
};
export const useDispatch = () => {
const { dispatch } = useContext(ToDosContext);
return dispatch;
};
export const useState = () => {
const { state } = useContext(ToDosContext);
return state;
};
export default ToDosProvider;