I need to display random quote from API using React hooks useState
and useEffect
.
import React, { useState, useEffect } from "react";
const API =
"https://gist.githubusercontent.com/camperbot/5a022b72e96c4c9585c32bf6a75f62d9/raw/e3c6895ce42069f0ee7e991229064f167fe8ccdc/quotes.json";
const App = () => {
const [quote, setQuote] = useState({
quotes: [],
index: 0,
});
useEffect(() => {
fetch(API)
.then((res) => {
return res.json();
})
.then((quote) => {
setQuote(quote);
console.log(quote.quotes[0].quote); // prints quote
console.log(quote.index); // prints undefined
});
}, []);
const getRandomIndex = () => {
setQuote((previosState) => {
return {
...previosState,
index: Math.floor(Math.random() * quote.quotes.length),
};
});
};
return (
<>
<p>this is quote: "{quote.quotes[index]}"</p>
</>
);
};
export default App;
In the useEffect
hook it prints correct quote, but it prints undefined for index.
Could you help me to print random quote here
<p>this is quote: "{quote.quotes[index]}"</p>
after index was randomly generated.
CodePudding user response:
you're going in the right way. Just some slight changes to make it work better.
- I separate
quotes
andindex
because the response is an object that has the "quotes" field, and not theindex
field. YoursetQuote(quote);
will setindex
to undefined. - Each item in
quotes
is an object which hasquote
andauthor
and ifquotes
is empty, [0] will be undefined, that's why I used nullish coalescing (?.
) inquotes[index]?.quote
.
import React, { useState, useEffect } from "react";
const API =
"https://gist.githubusercontent.com/camperbot/5a022b72e96c4c9585c32bf6a75f62d9/raw/e3c6895ce42069f0ee7e991229064f167fe8ccdc/quotes.json";
const getRandomInRange = (min, max) => {
return Math.floor(Math.random() * (max - min) min);
};
const App = () => {
const [quotes, setQuotes] = useState([]);
const [index, setIndex] = useState(0);
useEffect(() => {
fetch(API)
.then((res) => {
return res.json();
})
.then((data) => {
setQuotes(data.quotes);
});
}, []);
const setRandomIndex = () => {
setIndex(getRandomInRange(0, quotes.length));
};
return (
<>
<p>this is quote: {quotes[index]?.quote}</p>
<button onClick={setRandomIndex}>Another</button>
</>
);
};
export default App;
CodePudding user response:
Hey I adjusted your quote
state structure to be an array holding all the quotes that way you will not need to set random index
, we can easily load a random quote based on array index. See the updated App.js
here (I updated some of the namings and removed the getRandomIndex
since that's redundant:
import React, { useState, useEffect } from "react";
const API =
'https://gist.githubusercontent.com/camperbot/5a022b72e96c4c9585c32bf6a75f62d9/raw/e3c6895ce42069f0ee7e991229064f167fe8ccdc/quotes.json';
const App = () => {
const [quotes, setQuotes] = useState([]);
useEffect(() => {
fetch(API)
.then((res) => {
return res.json();
})
.then((quote) => {
setQuotes(quote.quotes);
});
}, []);
return (
<>
{console.log(quotes)}
<p>
this is quote: "
{quotes.length !== 0
? quotes[Math.floor(Math.random() * quotes.length)].quote
: 'Loading'}
"
</p>
</>
);
};
export default App;
Also this line of code in your question logs undefined
because quote
references to the data coming from API and it does not have index
property.
console.log(quote.index); // prints undefined because quote is from fetch and it does not have index property