简体   繁体   中英

How to display data from json in React

I try to create simple app that generate random quote. I created a function that (i think) get a data i want from json file. But when i try to pass that function to my App function i get Error: Objects are not valid as a React child (found: [object Promise])

function Quote:

function Quote (data) {
  var x = (Math.floor(Math.random() * (103 - 1) + 1) );
  return fetch('https://gist.githubusercontent.com/camperbot/5a022b72e96c4c9585c32bf6a75f62d9/raw/e3c6895ce42069f0ee7e991229064f167fe8ccdc/quotes.json')
  .then((response) => response.json())
  .then((responseJson) => {

    console.log(responseJson['quotes'][0]['author']);
    return responseJson['quotes'][x]['author'];
  })


  
  .catch((error) => {
    console.error(error);
  });
}

App function:

function App() {
  var text = '';
  return (
    
    <div id="quote-box">
      <div id="author"><Quote /></div>
      <button id="new-quote">New Quote</button>
      <a href="twitter.com" id="tweet-quote">Tweet</a>
    </div>
  );
}

I would use useEffect to trigger a call at the start. And use useState to save the value. And then also add the same logic to the onClick.

import { useEffect, useState } from "react";

function getQuote() {
  var x = Math.floor(Math.random() * (103 - 1) + 1);
  return fetch(
    "https://gist.githubusercontent.com/camperbot/5a022b72e96c4c9585c32bf6a75f62d9/raw/e3c6895ce42069f0ee7e991229064f167fe8ccdc/quotes.json"
  )
    .then((response) => response.json())
    .then((responseJson) => {
      console.log(responseJson["quotes"][0]["author"]);
      return responseJson["quotes"][x]["author"];
    })

    .catch((error) => {
      console.error(error);
    });
}

export default function App() {
  const [author, setAuthor] = useState("");

  useEffect(() => {
    getQuote().then((newAuthor) => setAuthor(newAuthor));
  }, []);
  return (
    <div id="quote-box">
      <div id="author">{author}</div>
      <button
        id="new-quote"
        onClick={() => getQuote().then((newAuthor) => setAuthor(newAuthor))}
      >
        New Quote
      </button>
      <a href="twitter.com" id="tweet-quote">
        Tweet
      </a>
    </div>
  )
}

You can also archive this way. Create a custom hooks and used it.

import React from "react";

function useFetchQuote(newQuote) {
  const [author, setAuthor] = React.useState();

  React.useEffect(() => {
    var x = Math.floor(Math.random() * (20 - 1) + 1);
    return fetch(
      "https://gist.githubusercontent.com/camperbot/5a022b72e96c4c9585c32bf6a75f62d9/raw/e3c6895ce42069f0ee7e991229064f167fe8ccdc/quotes.json"
    )
      .then((response) => response.json())
      .then((responseJson) => {
        console.log(responseJson["quotes"][x]["author"]);
        setAuthor(responseJson["quotes"][x]["author"]);
      })
      .catch((error) => {
        console.error(error);
      });
  }, [newQuote]);

  return { author };
}

function App() {
  const [newQuote, setQuote] = React.useState(0);
  const { author } = useFetchQuote(newQuote);

  return (
    <div id="quote-box">
      <div id="author">{author}</div>
      <button id="new-quote" onClick={() => setQuote(newQuote + 1)}>
        New Quote
      </button>
      <a href="twitter.com" id="tweet-quote">
        Tweet
      </a>
    </div>
  );
}

export default App;

Returning a promise in React components will not work like what you are doing in your code. React components must return a jsx . For example in a file named Quote.js

import * as React from 'react';

const url =
  'https://gist.githubusercontent.com/camperbot/5a022b72e96c4c9585c32bf6a75f62d9/raw/e3c6895ce42069f0ee7e991229064f167fe8ccdc/quotes.json';

const Qoute = () => {
  const [quote, setQuote] = React.useState(null);

  React.useEffect(() => {
    fetch(url)
      .then((response) => response.json())
      .then((data) => {
        const randomNumber = 1; // Generate random number which is lesser or equal to data's length
        setQuote(data['quotes'][randomNumber]);
      });
  }, []);

  if (!quote) return <React.Fragment>Loading...</React.Fragment>;

  return <div>{JSON.stringify(quote)}</div>;
};

export default Qoute;

Then you just need to import it somewhere where you would like to use it and invoke it like this

<Quote />

PS: I converted this from typescript if something is not working I'd be happy to help. And please remember to update the line where I place a comment. Goodluck, brother.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM