Asynchronously waiting for controller to return data to view?

Issue

I’m working with a MVC file structure and I’m trying to make a GET fetch request to obtain data from the backend. However, I can’t figure out how to asynchronously retrieve the data from the controller after the backend returns the data. As of now, it’s always returning undefined. Here are some code snippits:

View made with React:

var API = require('../Controllers');

function TakeOrder() {

   useEffect(()=> {        //fetchs menu from backend on first rendering of element
       setMenu(API.getMenu());
   }, []);

   const [menu, setMenu] = useState([]);

Controller:

const headers = (newHeader) => {
return {"Content-Type": "application/json", "Access-Control-Allow-Origin": "*", newHeader};
}

exports.getMenu = () => {
    fetch('/api', {
        headers: headers({"reqType": "get-menu"}),
    }).then(
    response => response.json()).then(
    data => {
        return data;
     })
}

Model uses Express:

app.get('/api', function(req, res){
   return res.json(menuItems);    
});

In the context of this example, I’d like to set menu to an array of MenuItems in the backend but the frontend isn’t waiting for the response from the Controller before setMenu is called.

Solution

You shouldn’t be passing that asynchronous function to setItem(), as state setters in React are not designed to wait for asynchronous tasks to finish. I would first change getMenu to:

exports.getMenu = async () => {
  const res = await fetch("/api", {
    headers: headers({ reqType: "get-menu" }),
  });
  const data = await res.json();
  return data;
};

Then the useEffect part to:

useEffect(() => {
  API.getMenu().then((data) => setData(data));
}, []);

Answered By – yousoumar

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published