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 afterward 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.
CodePudding user response:
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*/)
CodePudding user response:
If I understood correctly, you just want to fetch the data back when you delete a post, right?
I think, you need to trigger your useEffect properly.
You first need to modify an Array that contains todo items such that you must remove the item which you intend to remove from the backend in deleteToDo
and have it passed in useEffect
.
//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, <TodoArray>]);