1

I have an API endpoint located on my localhost:8000/ port; this endpoint simply returns the following object {"message": "hello"}.

I would like to grab this object using my React JS script. My script is added below.

import React, {useEffect, useState} from "react";

const App = () => {
    const [message, setMessage] = useState("");
    const getHomePageData = async () => {
        const requestOptions = {
            method: "GET",
            headers: {
                "Content-Type": "application/json",
            },
        };
        const response = await fetch("/", requestOptions)
        if (!response.ok) {
            console.log("Error in fetching the data!");
        } else {
            console.log("Data fetched correctly!");
        }
        return await response.json();
    };
    const data = getHomePageData();
    console.log(data);
    return(
        <center><h1>Hello, world!</h1></center>
    );
}
export default App;

Fetching the data seems to be working, because I'm getting the following log inside the console: Data fetched correctly! thus I think everything is working alright with my backend. However on the next line I get the following error message: Unhandled Promise Rejection: SyntaxError: The string did not match the expected pattern.

How can I fix my code to be able to get the .json() data?

Hendrra
  • 682
  • 1
  • 8
  • 19
  • Make `App` fn async and call the `const data = getHomePageData();` like this `const data = await getHomePageData();` – Joel Nov 03 '22 at 16:48
  • @Joel, I'm still getting the same error :( – Hendrra Nov 03 '22 at 16:50
  • Instead of `return await response.json()` write `const text = await response.text(); console.log(text); return JSON.parse(text);`. The check the console. I bet you're not getting what you expect from your endpoint. – Jared Smith Nov 03 '22 at 16:52
  • 2
    You can also check the network tab, filter on XHR requests, and check the response – Jared Smith Nov 03 '22 at 16:54
  • 1
    `fetch("/",` will probably return the html for `/` , `console.log(response)` to make sure you're getting the response you wanted – Taki Nov 03 '22 at 16:58
  • @Taki Well.. He is doing just that... on this line: `console.log(data);`. The problem is that he's not awaiting the response from the outer scope. `const data = await getHomePageData();`. But since you previously said on the answer that you deleted that the only difference between `.then` and `async/await` was syntactic sugar, I'm not gonna argue with you. Instead i leave you with this and let you read : https://www.geeksforgeeks.org/difference-between-promise-and-async-await-in-node-js/#:~:text=Promise%20is%20an%20object%20representing,the%20code%20execute%20more%20synchronously. – Joel Nov 03 '22 at 17:02
  • @Joel doing `const data = await getHomePageData();` this has no effect since it is not inside an `async` function .... – KcH Nov 03 '22 at 17:03
  • @KcH ‍♂️ read my initial comment... – Joel Nov 03 '22 at 17:04
  • @Joel my bad ... didn't see it – KcH Nov 03 '22 at 17:07
  • @Joel `console.log(data)` will show `Promise Pending` i meant `console.log(response)` which is right after `await fetch("/",...)` so he could see that the response is actually the index file and not the expected object, and i'm not sure why you put the link to that article, it says exactly the same thing `Async/Await is a syntactic sugar for promises` – Taki Nov 03 '22 at 17:12
  • @Taki You obviously do not understand the differences... Let me show you a simple demo :) https://stackblitz.com/edit/js-ljkrwn?file=index.js `.then` is going to finish some time in the future... whilst the program **awaits** for that line to be completed. You stop reading half-way... **Async/Await is a syntactic sugar for promises, *a wrapper making the code execute more synchronously*** – Joel Nov 03 '22 at 17:18
  • 2
    @Joel since when can react components be async? Or am I misreading what you're suggesting? – Jared Smith Nov 03 '22 at 17:21

2 Answers2

1

Try using useEffect:

import React, {useEffect, useState} from "react";

const App = () => {
    const [message, setMessage] = useState("");
    useEffect(() => {
      const getHomePageData = async () => {
        try {
          const requestOptions = {
            method: "GET",
            headers: {
                "Content-Type": "application/json",
            }
          };
          const response = await fetch("/", requestOptions)
          const data = await response.json();
          setMessage(data.message);
        } catch (error) {
          console.log(error);
        }
      };
      getHomePageData();
    }, []);
    return(
        <center><h1>Hello, world!</h1></center>
    );
}
export default App;
Majed Badawi
  • 27,616
  • 4
  • 25
  • 48
0

Majed's answer is probably the right way to wait for a promise in a react component without library.

However, if you are not too afraid to use library, tools like react-use-promise or react-query might help you to write more readable code.

const App = () => {
    const [message, error, state] = usePromise(async () => {
        const query = await fetch("/", {
            method: "GET",
            headers: {
                "Content-Type": "application/json",
            },
        })
        return await query.json();
    },
    [] // here the dependencies you use in your promise
  );
  return(
    <center><h1>Hello, world!</h1></center>
  );
}
Antonin Riche
  • 548
  • 6
  • 10