Adding New Todo Item to Backend¶
To let user add items to the database, we will first modify and existing action addItem
that will call our POST endpoint on backend, get the data and dispatch action to update our store and add item to the list.
export function addItem(title: string) {
return async (dispatch: any) => {
try {
const addTodoItem: any = await fetch('http://localhost:3001/todo', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
title,
})
});
const body = await addTodoItem.json();
if (addTodoItem.status !== 200) {
return dispatch({ type: 'ADD_ITEM_ERROR', message: body.message });
}
return dispatch({ type: 'ADD_ITEM_SUCCESS', item: body.todo });
} catch (error) {
return dispatch({ type: 'ADD_ITEM_ERROR', message: 'Something went wrong.' });
}
};
}
export function removeItem(item_id: number) {
return {
type: 'REMOVE_ITEM',
item_id
}
}
export function markItemAsDone(item_id: number) {
return {
type: 'MARK_ITEM_DONE',
item_id
}
}
export function getTodos() {
return async (dispatch: any) => {
try {
const todoList: any = await fetch('http://localhost:3001/todos', {
method: 'GET'
});
const body = await todoList.json();
if (todoList.status !== 200) {
return dispatch({ type: 'GET_TODOS_ERROR', message: body.message });
}
return dispatch({ type: 'GET_TODOS_SUCCESS', items: body.data });
} catch (error) {
return dispatch({ type: 'GET_TODOS_ERROR', message: 'Something went wrong.' });
}
};
}
ADD_ITEM_SUCCESS
that will dispatch action to reducer with todo item that was added to the database and ADD_ITEM_ERROR
that will be called in case something went wrong and pass error message to be stored in reducer.
If we for example send title "Todo 2", body
value should look like
{
"todo": {
"title": "Todo 2",
"is_done": false,
"_id": "85f358e91af25f1b4ad24bdd",
"__v": 0
}
}
Just like for getting todo items, we make sure that if anything else is wrong (like typos), we dispatch ADD_ITEM_ERROR
with default "Something went wrong." message in catch block.
Now we have 2 new action types to handle in our reducer ADD_ITEM_SUCCESS
and ADD_ITEM_ERROR
.
export interface Todo {
id: number;
title: string;
is_done: boolean;
}
interface TodoReducerInterface {
todo_list: Todo[],
error: '',
}
const INITIAL_STATE: TodoReducerInterface = {
todo_list: [],
error: '',
}
const todoReducer = (state = INITIAL_STATE, action: any) => {
switch (action.type) {
case "ADD_ITEM_SUCCESS":
return {
...state,
todo_list: [
...state.todo_list,
action.item
]
}
case "ADD_ITEM_ERROR":
return {
...state,
error: action.message,
}
case "REMOVE_ITEM":
const removeItemIndex = state.todo_list.findIndex((item: any) => item.id === action.item_id);
if (removeItemIndex < 0) {
return state;
}
return {
...state,
todo_list: [
...state.todo_list.slice(0, removeItemIndex),
...state.todo_list.slice(removeItemIndex + 1),
]
}
case "MARK_ITEM_DONE":
const doneItemIndex: number = state.todo_list.findIndex((item: any) => item.id === action.item_id);
if (doneItemIndex < 0) {
return state;
}
return {
...state,
todo_list: [
...state.todo_list.slice(0, doneItemIndex),
{
...state.todo_list[doneItemIndex],
is_done: !state.todo_list[doneItemIndex].is_done
},
...state.todo_list.slice(doneItemIndex + 1),
]
}
case "GET_TODOS_SUCCESS":
return {
...state,
todo_list: action.items,
error: '',
}
case "GET_TODOS_ERROR":
return {
...state,
todo_list: [],
error: action.message
}
default:
return state;
}
};
export default todoReducer;
Now, we can try to add a new todo item through application with title "Todo 2". Inpunt "Todo 2" inside input box and hit "+ Add" button.
If you did everything as you should, a new item will be added to database and will appear in the list.
We successfully added a new item to database and displayed it. In the next part we will make users able to remove an existing item from the database with provided id and automatically remove it from the list.