this is the code:
class QuoteBox extends React.Component {
constructor(props){
super(props);
this.state = {
quotes: Data,
current: Data[0]
}
}
setRandomQuote(){
const index = Math.floor(Math.random() * this.state.quotes.length);
this.setState({
current: this.state.quotes[index]
})
}
render(){
return <div id="quote-box">
<p id="text">
{this.state.current.quote}
</p>
<h5 id="auther">
{this.state.current.author}
</h5>
<button onClick={this.setRandomQuote} id="new-quote">New Quote</button>
<a href="" id="tweet-quote">haha</a>
</div>
}
};
and am getting this error message:
TypeError: Cannot read property 'state' of undefined
setRandomQuote
src/Components/QuoteBox/quoteBox.js:15
12 | }
13 |
14 | setRandomQuote(){
> 15 | const index = Math.floor(Math.random() * this.state.quotes.length);
| ^ 16 | this.setState({
17 | current: this.state.quotes[index]
18 | })
View compiled
▶ 19 stack frames were collapsed.
why state is undefined when it has been initialized in the constructor, Im new to react so i would like to understand exactly what is happening and why. thanks.
There are several ways to deal with this, the two most common approaches for class components are to bind the function to the component or to use an arrow function. Examples of both follow.
Function binding in the constructor:
constructor(props){
super(props);
this.state = {
quotes: Data,
current: Data[0]
}
this.setRandomQuote = this.setRandomQuote.bind(this)
}
Using an arrow function: (thanks @Linda Paiste)
setRandomQuote = () => {
const index = Math.floor(Math.random() * this.state.quotes.length);
this.setState({
current: this.state.quotes[index]
})
}
However, if you're just getting started I would strongly encourage you to use functional components and be careful with any materials you read that use class based components, as they may be dated.
Below is your class, refactored to a functional component. Make sure you import {useState) from react.
const QuoteBox = () => {
const [state, setState] = useState({
quotes: Data,
current: Data[0]
})
const setRandomQuote = () => {
const index = Math.floor(Math.random() * state.quotes.length);
setState({
...state,
current: state.quotes[index]
})
}
return (<div id="quote-box">
<p id="text">
{state.current.quote}
</p>
<h5 id="auther">
{state.current.author}
</h5>
<button onClick={setRandomQuote} id="new-quote">New Quote</button>
<a href="" id="tweet-quote">haha</a>
</div>
)
};