8. When the #new-quote button is clicked, my quote machine should fetch a new quote and display it in the #text element

Hi folks, I am having issues with this “When the #new-quote button is clicked, my quote machine should fetch a new quote and display it in the #text element.” I have tried the handleClick function not to no avail.
It works as expected with vscode by generating quotes when the button is clicked. But it fails in codepen. Help is needed. My code without the html is as follows:

 const quotesObject =[
  {author: "Kofi Sam", quote: "He is good"},
  {author: "Sam Art", quote: "Who among the gods can be compared to You"},
  {author: "Yaw Amoah", quote: "You reign in majesty and holiness"},
  {author: "John Rice", quote: "You reign forever more"},
  {author: "Sarah Toods", quote: "You are the king of glory"},
  {author: "Mary Mensah", quote: "You are the prince of peace"},
  {author: "James Ho", quote: "I worship You"},
  {author: "king France", quote: "I adore You"},
  {author: "Yaw Kofi", quote: "I praise your holy name"}
]

class App extends React.Component{
  constructor(){
    super()
    this.state = {
      author: '',
      quote: ''      
    }
    this.handleClick = this.handleClick.bind(this)
  }
  componentDidMount(){
    let indx = Math.floor(Math.random() * quotesObject.length)
    this.setState({
      author: quotesObject[indx]['author'],
      quote: quotesObject[indx]['quote']
    })
  }
  handleClick(){
    let indx = Math.floor(Math.random() * quotesObject.length)
    
    this.setState({
      return{
         author: quotesObject[indx]['author'],
         quote: quotesObject[indx]['quote']
      }
    })
  }
  render(){
    return(
      <div id="quote-box">
        <div>
           <i className="fa fa-quote-left"></i><span id="text">{this.state.quote}</span> 
           <h2>-<span id="author">{this.state.author}</span></h2>
        </div>  
       
          <button class="button" id="new-quote" onClick={this.handleClick}>New quote</button>
      </div>  
    )
  }
  
}

You would only use the return keyword here if you were using the functional form of setState method. Otherwise, you just need add the property/value pairs in the object returned.
SPOILER!!!

    this.setState({
      author: quotesObject[indx]['author'],
      quote: quotesObject[indx]['quote']
    });

Thanks for the reply. I have tried that already. I will remove the return statement and see what will happen.

Also, you can simplify your handleClick function by using object destructuring here:

  handleClick(){
    const indx = Math.floor(Math.random() * quotesObject.length);
    const { author, quote } = quotesObject[indx];
    this.setState({ author, quote }); 
  }

Thanks will try this one too.

It replies with a timeout error as follows:

Timeout of 15000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.
Error: Timeout of 15000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.
    at i.p._timeoutError (https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:598:36139)
    at https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:598:34258

Can you please post your latest code? Better yet, can you post a link to your code (i.e. Codepen)?

Sure.

const quotesObject =[
  {author: "Kofi Sam", quote: "He is good"},
  {author: "Sam Art", quote: "Who among the gods can be compared to You"},
  {author: "Yaw Amoah", quote: "You reign in majesty and holiness"},
  {author: "John Rice", quote: "You reign forever more"},
  {author: "Sarah Toods", quote: "You are the king of glory"},
  {author: "Mary Mensah", quote: "You are the prince of peace"},
  {author: "James Ho", quote: "I worship You"},
  {author: "king France", quote: "I adore You"},
  {author: "Yaw Kofi", quote: "I praise your holy name"}
]

class App extends React.Component{
  constructor(){
    super()
    this.state = {
      author: '',
      quote: ''      
    }
    this.handleClick = this.handleClick.bind(this)
  }
  componentDidMount(){
    let indx = Math.floor(Math.random() * quotesObject.length)
    this.setState({
      author: quotesObject[indx]['author'],
      quote: quotesObject[indx]['quote']
    })
  }
  handleClick(){
    let indx = Math.floor(Math.random() * quotesObject.length)
    const { author, quote } = quotesObject[indx]
    this.setState({author, quote})
  }
  render(){
    return(
      <div id="quote-box">
        <div>
           <i className="fa fa-quote-left"></i><span id="text">{this.state.quote}</span> 
           <h2>-<span id="author">{this.state.author}</span></h2>
        </div>  
       
          <button class="button" id="new-quote" onClick={this.handleClick}>New quote</button>
      </div>  
    )
  }
  
}


My guess is you do not have enough quotes. The particular test you are failing is trying to validate a different quote is found between clicks. Since you are randomly selecting one, it is possible that the same quote would be picked as the very next quote when the button is clicked. You have two ways to fix this:

  1. Add a lot more quotes

OR

  1. Make sure the next quote displayed is different than the previous quote displayed.

Thanks very much. I will just do that.

FYI - You don’t need componentDidMount here. Instead, you could create a method (let’s call it getRandomQuote) that randomly selects one of the objects in the quotesObject array (which I think should be renamed to quotesArray). Then inside your constructor you would simply call the method/function and assign to this.state

this.state = this.getRandomQuote();

Then, your handleClick method simply becomes:

  handleClick() {
    this.setState(this.getRandomQuote());
  }

and then you can delete the componentDidMount method.

1 Like

Thanks sir. I will try this.

Hi Randell, I have tried the suggestions which you gave to me. But still the timeout error persists. I will be happy if new you give me new suggestions. Thanks.

Here is my new codes:

const quotesObject =[
  {author: "Kofi Sam", quote: "He is good"},
  {author: "Sam Art", quote: "Who among the gods can be compared to You"},
  {author: "Yaw Amoah", quote: "You reign in majesty and holiness"},
  {author: "John Rice", quote: "You reign forever more"},
  {author: "Sarah Toods", quote: "You are the king of glory"},
  {author: "Mary Mensah", quote: "You are the prince of peace"},
  {author: "James Ho", quote: "I worship You"},
  {author: "king France", quote: "I adore You"},
  {author: "Yaw Kofi", quote: "I praise your holy name"},
  {author: "Zebra Crossing", quote: "Rain or shine, successful"},
  {author: "Ama Smith", quote: "The day is bright"},
  {author: "Duke Wellington", quote: "It is good to be a human being"},
  {author: "Bernard Arthur", quote: "How can they fail if they are hard working?"},
   {author: "Kofi Sam", quote: "He is good"},
  {author: "Billy Bones", quote: "I lived at the old Benbow"},
  {author: "hope aikins", quote: "Very good and nice can be your accolade"},
  {author: "ken louis", quote: "He is king forever more"},
  {author: "Simon Templer", quote: "He is the king of glory"},
  {author: "Martha Menson", quote: "He is the prince of peace"},
  {author: "Davis Ho", quote: "We worship Him"},
  {author: "Kerry Fynn", quote: "We adore You"},
  {author: "Yamson", quote: "We praise your holy name"},
  {author: "George Native", quote: " successful is our hallmark"},
  {author: "Sally Settings", quote: "The night is dark but good"},
  {author: "David Prince", quote: "It is good to be a developer"},
  {author: "Collins Abban", quote: "He is hardworking"}
]

class App extends React.Component{
  constructor(){
    super()
    this.state = this.getRandomQuote();
    this.handleClick = this.handleClick.bind(this)
  }
  getRandomQuote(){
    let indx = Math.floor(Math.random() * quotesObject.length)
    this.setState({
      author: quotesObject[indx]['author'],
      quote: quotesObject[indx]['quote']
    })
  }
  handleClick(){
   getRandomQuote()
  }
  render(){
    return(
      <div id="quote-box">
        <div>
           <i className="fa fa-quote-left"></i><span id="text">{this.state.quote}</span> 
           <h2>-<span id="author">{this.state.author}</span></h2>
        </div>  
       
          <button class="button" id="new-quote" onClick={this.handleClick}>New quote</button>
      </div>  
    )
  }
  
}

Sorry, this is a corrected version:

const quotesObject =[
  {author: "Kofi Sam", quote: "He is good"},
  {author: "Sam Art", quote: "Who among the gods can be compared to You"},
  {author: "Yaw Amoah", quote: "You reign in majesty and holiness"},
  {author: "John Rice", quote: "You reign forever more"},
  {author: "Sarah Toods", quote: "You are the king of glory"},
  {author: "Mary Mensah", quote: "You are the prince of peace"},
  {author: "James Ho", quote: "I worship You"},
  {author: "king France", quote: "I adore You"},
  {author: "Yaw Kofi", quote: "I praise your holy name"},
  {author: "Zebra Crossing", quote: "Rain or shine, successful"},
  {author: "Ama Smith", quote: "The day is bright"},
  {author: "Duke Wellington", quote: "It is good to be a human being"},
  {author: "Bernard Arthur", quote: "How can they fail if they are hard working?"},
   {author: "Kofi Sam", quote: "He is good"},
  {author: "Billy Bones", quote: "I lived at the old Benbow"},
  {author: "hope aikins", quote: "Very good and nice can be your accolade"},
  {author: "ken louis", quote: "He is king forever more"},
  {author: "Simon Templer", quote: "He is the king of glory"},
  {author: "Martha Menson", quote: "He is the prince of peace"},
  {author: "Davis Ho", quote: "We worship Him"},
  {author: "Kerry Fynn", quote: "We adore You"},
  {author: "Yamson", quote: "We praise your holy name"},
  {author: "George Native", quote: " successful is our hallmark"},
  {author: "Sally Settings", quote: "The night is dark but good"},
  {author: "David Prince", quote: "It is good to be a developer"},
  {author: "Collins Abban", quote: "He is hardworking"}
]

class App extends React.Component{
  constructor(){
    super()
    this.state = this.getRandomQuote();
    this.handleClick = this.handleClick.bind(this)
  }
  getRandomQuote(){
    let indx = Math.floor(Math.random() * quotesObject.length)
    this.setState({
      author: quotesObject[indx]['author'],
      quote: quotesObject[indx]['quote']
    })
  }
  handleClick(){
   this.getRandomQuote()
  }
  render(){
    return(
      <div id="quote-box">
        <div>
           <i className="fa fa-quote-left"></i><span id="text">{this.state.quote}</span> 
           <h2>-<span id="author">{this.state.author}</span></h2>
        </div>  
       
          <button class="button" id="new-quote" onClick={this.handleClick}>New quote</button>
      </div>  
    )
  }
  
}

The last two post of code do not work at all. There are many errors showing in the browser console.

Your getRandomQuote method should not be setting state. That should happen in the handleClick method. All getRandomQuote should do is return an object with quote and author properties/values.

Thanks I will correct it. Kindly have a look at the new version.

const quotesObject =[
  {author: "Kofi Sam", quote: "He is good"},
  {author: "Sam Art", quote: "Who among the gods can be compared to You"},
  {author: "Yaw Amoah", quote: "You reign in majesty and holiness"},
  {author: "John Rice", quote: "You reign forever more"},
  {author: "Sarah Toods", quote: "You are the king of glory"},
  {author: "Mary Mensah", quote: "You are the prince of peace"},
  {author: "James Ho", quote: "I worship You"},
  {author: "king France", quote: "I adore You"},
  {author: "Yaw Kofi", quote: "I praise your holy name"},
  {author: "Zebra Crossing", quote: "Rain or shine, successful"},
  {author: "Ama Smith", quote: "The day is bright"},
  {author: "Duke Wellington", quote: "It is good to be a human being"},
  {author: "Bernard Arthur", quote: "How can they fail if they are hard working?"},
   {author: "Urish more", quote: "Who is good"},
  {author: "Billy Bones", quote: "I lived at the old Benbow"},
  {author: "hope aikins", quote: "Very good and nice can be your accolade"},
  {author: "ken louis", quote: "He is king forever more"},
  {author: "Simon Templer", quote: "He is the king of glory"},
  {author: "Martha Menson", quote: "He is the prince of peace"},
  {author: "Davis Ho", quote: "We worship Him"},
  {author: "Kerry Fynn", quote: "We adore You"},
  {author: "Yamson", quote: "We praise your holy name"},
  {author: "George Native", quote: " successful is our hallmark"},
  {author: "Sally Settings", quote: "The night is dark but good"},
  {author: "David Prince", quote: "It is good to be a developer"},
  {author: "Collins Abban", quote: "He is hardworking"}
]

class App extends React.Component{
  constructor(){
    super()
    this.state = {
      author: '',
      quote: ''
    }
    this.handleClick = this.handleClick.bind(this)
  }
  getRandomQuote(){
    let indx = Math.floor(Math.random() * quotesObject.length)
    this.setState({
      author: quotesObject[indx]['author'],
      quote: quotesObject[indx]['quote']
    })
  }
  handleClick(){
   this.getRandomQuote()
  }
  render(){
    return(
      <div id="quote-box">
        <div>
           <i className="fa fa-quote-left"></i><span id="text">{this.state.quote}</span> 
           <h2>-<span id="author">{this.state.author}</span></h2>
        </div>  
       
          <button class="button" id="new-quote" onClick={this.handleClick}>New quote</button>
      </div>  
    )
  }
  
}

You need to look out the browser’s console. You have a syntax error on the button element.

Also, although not a problem technically, I recommend not using the setState in the getRandomQuote method. Instead, use it in the handleClick method. This way, you can use the getRandomQuote method to initialize this.state in the constructor.

Thanks, I have tried the new solution. Kindly have a look at the new codes

const quotesObject =[
  {author: "Kofi Sam", quote: "He is good"},
  {author: "Sam Art", quote: "Who among the gods can be compared to You"},
  {author: "Yaw Amoah", quote: "You reign in majesty and holiness"},
  {author: "John Rice", quote: "You reign forever more"},
  {author: "Sarah Toods", quote: "You are the king of glory"},
  {author: "Mary Mensah", quote: "You are the prince of peace"},
  {author: "James Ho", quote: "I worship You"},
  {author: "king France", quote: "I adore You"},
  {author: "Yaw Kofi", quote: "I praise your holy name"},
  {author: "Zebra Crossing", quote: "Rain or shine, successful"},
  {author: "Ama Smith", quote: "The day is bright"},
  {author: "Duke Wellington", quote: "It is good to be a human being"},
  {author: "Bernard Arthur", quote: "How can they fail if they are hard working?"},
   {author: "Urish more", quote: "Who is good"},
  {author: "Billy Bones", quote: "I lived at the old Benbow"},
  {author: "hope aikins", quote: "Very good and nice can be your accolade"},
  {author: "ken louis", quote: "He is king forever more"},
  {author: "Simon Templer", quote: "He is the king of glory"},
  {author: "Martha Menson", quote: "He is the prince of peace"},
  {author: "Davis Ho", quote: "We worship Him"},
  {author: "Kerry Fynn", quote: "We adore You"},
  {author: "Yamson", quote: "We praise your holy name"},
  {author: "George Native", quote: " successful is our hallmark"},
  {author: "Sally Settings", quote: "The night is dark but good"},
  {author: "David Prince", quote: "It is good to be a developer"},
  {author: "Collins Abban", quote: "He is hardworking"}
]

class App extends React.Component{
  constructor(){
    super()
    this.state = {
      author: '',
      quote: ''
    }
    this.handleClick = this.handleClick.bind(this)
  }
  getRandomQuote(){
    let indx = 0;
    indx = Math.floor(Math.random() * quotesObject.length) 
    return indx
  }
  
  handleClick(){
   let newIndx = this.getRandomQuote()
    
    this.setState({
      author: quotesObject[newIndx]['author'],
      quote: quotesObject[newIndx]['quote']
    })
  }
  render(){
    return(
      <div id="quote-box">
        <div>
           <i className="fa fa-quote-left"></i><span id="text">{this.state.quote}</span> 
           <h2>-<span id="author">{this.state.author}</span></h2>
        </div>  
       
          <button className="button" id="new-quote" onClick={this.handleClick}>New quote</button>
      </div>  
    )
  }
  
}

I also see this error after testing:

Timeout of 15000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.
Error: Timeout of 15000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.
    at i.p._timeoutError (https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:598:36139)
    at https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js:598:34258

var e;return this.timeout(15e3),e=document.getElementById("text").innerText,document.getElementById("new-quote").click(),new Promise(function(t){var r=setInterval(function(){document.getElementById("text").innerText!==e&&(clearInterval(r),t())},500)})

The latter part of the error is point to a promise not being handled properly. This is beyound my reach since handling this part of test is not part of the requirements for 8th test case. Can I report this as a bug?