Been banging my ahead against a wall on this one for a while. Doing the FCC course, essentially completed a project but trying to fetch a JSON with an array rather than just putting one in directly, myself, as I wanted to learn how to do it... Didn't think it would be this difficult!
What do I want to do?
I want to fetch a json and assign the array within it to state within my react component. I'll then use a random num gen to pick a random quote to display from the array.
Where am I having trouble?
I'm able to fetch the json and log the quotes to the console, however whenever I try to assign them to a variable, I end up with the promise object. I think it's a problem that I must've misunderstood/not quite wrapped my head around asynchronous functions yet
What I need help with
I've created a new codepen, separate to the task, where I have been testing how to get this to work without React, so I can then work it into my React project when I know what to do.
I'm able to log the first quote in the array to the console when I run the async function, however when I try to use that same async function to return that quote to myQuote, it returns a Pending Promise. Am I approaching this correctly at all, or am I completely going in the wrong direction?
If you don't want to visit the codepen link, code below:
const testFetch = fetch('https://gist.githubusercontent.com/camperbot/5a022b72e96c4c9585c32bf6a75f62d9/raw/e3c6895ce42069f0ee7e991229064f167fe8ccdc/quotes.json')
.then(response => response.json())
.then((quote) => {
return quote.quotes;
})
// The console.log below logs "The quote is [quote as a string]" to the console
const testVar = async () => {
const quoteArr = await testFetch;
console.log("The quote is ", quoteArr[0].quote);
return quoteArr[0].quote;
};
let myQuote = testVar();
// This logs "Is my quote variable working? [Promise pending]" to the console
console.log("Is my quote variable working? ", myQuote)
CodePudding user response:
A common pattern in react (although not the best one) is to call fetch in useEffect and set the state in .then.
The simplest example would be
import React, { useEffect, useState } from "react";
const App = () => {
const [quotes, setQuotes] = useState<any>([]);
useEffect(() => {
fetch(
"https://gist.githubusercontent.com/camperbot/5a022b72e96c4c9585c32bf6a75f62d9/raw/e3c6895ce42069f0ee7e991229064f167fe8ccdc/quotes.json"
)
.then((response) => response.json())
.then((quote) => {
setQuotes(quote.quotes);
});
}, [setQuotes]);
return (
<div>
{quotes.length > 0 && quotes.map((quote: any) => <div>{quote.quote}</div>)}
</div>
);
};
export default App;
A modern alternative in React is to use ReactQuery for fetching data, as it provides nice abstractions and caching out of the box.
CodePudding user response:
In react, you need to load data after the render into the state. You can not just globally fetch and get data correctly. The below code will clarify.
const testFetch = fetch('https://gist.githubusercontent.com/camperbot/5a022b72e96c4c9585c32bf6a75f62d9/raw/e3c6895ce42069f0ee7e991229064f167fe8ccdc/quotes.json')
.then(response => response.json())
.then((quote) => {
return quote.quotes;
})
const MyComponent = () => {
useEffect(()=>{
testFetch.then(quoteArr => {
console.log('The quote is ', quoteArr[0].quote);
});
},[])
}
CodePudding user response:
This syntax is equivalent to the async/await syntax in that it is resolving the promise. It's a redundancy using both.
const testFetch = fetch('https://gist.githubusercontent.com/camperbot/5a022b72e96c4c9585c32bf6a75f62d9/raw/e3c6895ce42069f0ee7e991229064f167fe8ccdc/quotes.json')
.then(response => response.json())
.then((quote) => {
return quote.quotes;
})
You can try something like this
// you must also use react state to save your data
const [state, setState] = useState()
const testFetch = async () => {
// with this syntax you need to wrap it in a try/catch to catch your errors
try {
// res here is equivalent to [response] above
const res = await fetch('https://gist.githubusercontent.com/camperbot/5a022b72e96c4c9585c32bf6a75f62d9/raw/e3c6895ce42069f0ee7e991229064f167fe8ccdc/quotes.json')
console.log(res)
return res
} catch (err) {
console.log(err)
return
}
}
// and called upon component mount using useeffect
useEffect(() => {
const testVar = testFetch()
setState(testVar)
}, [])