Trying to Build Random quote api app with React. When first time app loads on Button Click it generates the random quote. But on Second Click App Crashes with "Error occured in App Component" "Consider adding an error boundary to your tree to customize error handling behavior.
class App extends React.Component {
state = {
quotes: null
};
componentDidMount() {
fetch("https://gist.githubusercontent.com/camperbot/5a022b72e96c4c9585c32bf6a75f62d9/raw/e3c6895ce42069f0ee7e991229064f167fe8ccdc/quotes.json")
.then(res => res.json())
.then(data => {
// console.log(data);
this.setState({
quotes: data.quotes
});
});
// console.log(this.state.quotes);
}
randomQuoteHandler = () => {
const randNumb = Math.floor(Math.random() * this.state.quotes.length);
const randomQuote = this.state.quotes[randNumb];
this.setState({
quotes: randomQuote
});
console.log(this.state.quotes);
};
render() {
return (
<div>
<button onClick={this.randomQuoteHandler}>gen</button>
<p>{this.state.quotes !== null && this.state.quotes.quote}</p>
<p> {this.state.quotes !== null && this.state.quotes.author}</p>
</div>
);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
Reason to Use: Suppose there is an error in JavaScript inside component then it used to corrupt React's internal state and cause it to emit cryptic errors. Error boundaries help in removing these errors and display a Fallback UI instead(Which means a display of an error that something broke in the code).
Error Boundaries are only designed for intercepting errors that originate from 3 places in a React component: During render phase. In a lifecycle method. In the constructor.
In order to use Error Boundary in Functional Component, I use react-error-boundary. When we run this application, we will get a nice error display form the content of ErrorHandler component. React error boundary catches any error from the components below them in the tree.
As of v16. 2.0, there's no way to turn a functional component into an error boundary. The React docs are clear about that, although you're free to reuse them as many times as you wish: The componentDidCatch() method works like a JavaScript catch {} block, but for components.
The randomQuoteHandler
replaces this.state.quotes
array with a chosen quote
which is an object. So on the second click, this.state.quotes.length
is undefined.
You need to store the chosen quote in another state variable like randomQuote
.
class App extends React.Component {
state = {
quotes: null,
randomQuote: null,
}
componentDidMount() {
fetch(
'https://gist.githubusercontent.com/camperbot/5a022b72e96c4c9585c32bf6a75f62d9/raw/e3c6895ce42069f0ee7e991229064f167fe8ccdc/quotes.json',
)
.then(res => res.json())
.then(data => {
// console.log(data);
this.setState({
quotes: data.quotes,
})
})
// console.log(this.state.quotes);
}
randomQuoteHandler = () => {
const randNumb = Math.floor(Math.random() * this.state.quotes.length)
const randomQuote = this.state.quotes[randNumb]
this.setState({
randomQuote: randomQuote,
})
console.log(this.state.quotes)
}
render() {
return (
<div>
<button onClick={this.randomQuoteHandler}>gen</button>
<p>{this.state.randomQuote !== null && this.state.randomQuote.quote}</p>
<p>{this.state.randomQuote !== null && this.state.randomQuote.author}</p>
</div>
)
}
}
The problem is that in the randomQuoteHandler
you are replacing the whole array of quotes
with the random randomQuote
object. The log
at the end of this randomQuoteHandler
function is showing that.
this.setState({
quotes: randomQuote // Array get replaced by one object
});
therefore the second time there is no array in the sate to read this.state.quotes.quote
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With