0

I am fetching a quotes API. Here I want to update the quotes randomly but I want to update the quotes on button click. I have no idea how to do that. Can anyone help me to do so?

I have fetched data using fetch request then add data to state.

This is my code

import React from "react";    
import "./styles.css";    
class Box extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      quote: "",
      author: ""
    };
  }    
  componentDidMount() {
    this.fetchData();
  }
  fetchData = () => {
    fetch(
      "https://gist.githubusercontent.com/camperbot/5a022b72e96c4c9585c32bf6a75f62d9/raw/e3c6895ce42069f0ee7e991229064f167fe8ccdc/quotes.json"
    )
      .then(result => {
        return result.json();
      })
      .then(data => {
        const ran = Math.floor(Math.random() * data.quotes.length);       
        console.log(data.quotes[ran].quote);
        console.log(data.quotes[ran].author);
        this.setState({
          quote: data.quotes[ran].quote,
          author: data.quotes[ran].author
        });
      });
  };

  render() {
    return (
      <div id="quote-box" className="container">
        <div className="box-container">
          <div className="text-center">
            <h1 id="text">{this.state.quote}</h1>
          </div>
          <div className="float-right">
            <p id="author">
              <span>- </span>
              {this.state.author}
            </p>
          </div>
        </div>
        <div className="box-item">
          <div className="row">
            <div className="col-sm-6">Twitter</div>
            <div className="col-sm-6">
              <button>next quote</button>  <--- Here i want this button to update quotes on screen.
            </div>
          </div>
        </div>
      </div>
    );
  }
}

export default Box;
1
  • Why not just call this.fetchData again? Or store all the quotes the first time you call it, so you can generate a new random index without another network call? Commented Jun 7, 2019 at 7:35

2 Answers 2

2

First thing is, store the quote array that you've fetched to a state so you wont need to fetch it again when you want to display another quote.

this.state = {
  quoteArray: [],  <----- This one
  quote: "",
  author: ""
};

Then create a separate function that will get random quote from that quoteArray

pickRandomQuote = () => {
   const ran = Math.floor(Math.random() * data.quotes.length);      
   this.setState({
     quote: this.state.quoteArray[ran].quote,
     author: this.state.quoteArray[ran].author
   });
}

In your fetch function, store the array you fetched to the state and then call the pickRandomQuote after

fetchData = () => {
    fetch(
"https://gist.githubusercontent.com/camperbot/5a022b72e96c4c9585c32bf6a75f62d9/raw/e3c6895ce42069f0ee7e991229064f167fe8ccdc/quotes.json"
    )
      .then(result => {
        return result.json();
      })
      .then(data => {
        this.setState({
          quoteArray: data
        });
        this.pickRandomQuote();
      });
  };

Then to generate new random quote, just put this to your button

<button onClick={() => this.pickRandomQuote()}>next quote</button>
Sign up to request clarification or add additional context in comments.

Comments

1

render: <button onClick={this.fetchData}>next quote</button>

constructor:

constructor(props) {
  super(props);
  this.state = {
    quote: "",
    author: ""
  };
  this.fetchData = this.fetchData.bind(this);
}

2 Comments

Thank you actually I forgot to bind the function that's why I was getting infinite loop may be.
This is not a good idea because it will unnecessarily fetch new data every button click. Check my answer on how to properly do it

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.