0

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>
  );
}
1
  • 2
    Your Quote is not a React component. It's a function that returns a promise. I think you need to read the docs here to understand better how react components work. Commented Oct 26, 2021 at 11:47

3 Answers 3

2

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>
  )
}
Sign up to request clarification or add additional context in comments.

1 Comment

Oh my god it works ^^ thanks you a lot i was trying to do this about 10 hours
0

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;

Comments

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.