Basically I'm working on creating a ToDo app with CRUD operations, however, when I POST or DELETE a document from MongoDB, I'd like my hook to auto fetch the results. I can feel that this is a simple fix and I've tried some weird things including useCallback
but nothing seems to work. Here's my hook:
import { useCallback, useEffect, useState } from 'react';
import axios from 'axios';
export const useAPI = () => {
const backendURL = '<InsertURL>.com/api/todos';
const [retrievedData, setRetrievedData] = useState([]);
//sends todo to database
const postToDo = useCallback(async (newToDo) => {
await axios
.post(backendURL, newToDo)
.catch((error) => console.log(error.message));
}, []);
//deletes a todo from the database
const deleteToDo = async (todo) => {
console.log(todo);
await axios
.delete(backendURL, todo)
.catch((error) => console.log(error.message));
};
//gets todos from database
useEffect(() => {
const getToDos = async () => {
await axios
.get(backendURL)
.then((fetchedData) => {
setRetrievedData(fetchedData.data.todos);
})
.catch((error) => console.log(error.message));
};
getToDos();
}, [postToDo]);
return { retrievedData, postToDo, deleteToDo };
};
Basically, I want postToDo
to be called and then for getToDos
to execute immediately afterwards without having to refresh the page. I'll want to use this same technique to with deleteToDo
.
Why useCallback
? Because ESlinter told me to do it if I put postToDo
in getToDos
dependency. I thought if I put postToDo
in the array it would update when the function was called, but that doesn't seem to be the case. I'm also worried about trying too many weird things because I added 30+ documents to my database on accident when it auto executed a bunch of times.
Abstracting away your React hooks, you can sequence asynchronous actions by using the .then
promise syntax (as one example):
const postToDos = async (newToDo) => {
await axios
.post(backendURL, newToDo)
.catch((error) => console.log(error.message))
}
const getToDos = async () => {
await axios.get(backendURL)
}
postToDos(newToDo).then(getToDos).then(fetchedData => {
setRetrievedData(fetchedData.data.todos)
})
Or, you can combine the async/await syntax into a single function
const postToDos = async (newToDo) => {
await axios
.post(backendURL, newToDo)
.catch((error) => console.log(error.message))
}
const getToDos = async () => {
await axios.get(backendURL)
}
const postAndGetToDos = async (newToDo) => {
await postToDo(newToDo)
var fetchedData = await getToDos()
setRetrievedData(fetchedData.data.todos)
}
postAndGetToDos({/*new toDo object*/)