Home > Software design >  React render API using hooks
React render API using hooks

Time:12-31

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.

  1. I separate quotes and index because the response is an object that has the "quotes" field, and not the index field. Your setQuote(quote); will set index to undefined.
  2. Each item in quotes is an object which has quote and author and if quotes is empty, [0] will be undefined, that's why I used nullish coalescing (?.) in quotes[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
  • Related