Hi,
I’m currently going through the Front End Development Library certificate, and I’m building the Random Quote Machine.
I know React is overkill for this, but I’ve decided to go with it anyway to test my knowledge so far, before starting to study Redux.
Anyway, I build the App locally using create-react-app (I don’t really like Codepen), and I got all the basic functionality working and passing the tests.
I’m having an issue though (more than one actually, but let’s try to solve this one): as generating a random index for fetching the quotes (I have them in an array in a separate file) can sometimes result in quotes repetition, I’ve decided to generate the array order
of shuffled indexes which are then used to fetch the quotes.
The array is generated in the componentDidMount
method (line 22), and from there passed into the main component QuoteBox
state (line 34).
In the render()
method (line 45) I have a variable quote
which should be assigned the current quote;
however, when I try to access the quotesArr
like so:
let quote = '"' + quotesArr[this.state.order[this.state.quoteCount]].quote + '"';
the app breaks and I have the following error:
quotesArr[this.state.order[this.state.quoteCount]] is undefined.
For debugging purposes, I’m visualizing the index I’m using to access the quotesArr
in the p
element in line 58, and it shows correctly.
I suspect the problem is in the syntax but I don’t understand what is going on. Any ideas? Here’s the code:
import React from 'react';
//import { react } from '@babel/types';
import ReactFCCtest from 'react-fcctest';
import './styles/App.css';
import { quotesArr } from './quotes.js'; /*quotesArr = [ { quote: '...', author: '...', from: '...' }, {...}, {...} ];
not every quote obj has a 'from' key */
class QuoteBox extends React.Component {
constructor(props) {
super(props);
this.state = {
order: [],
quoteCount: 0
}
this.getNewQuote = this.getNewQuote.bind(this);
}
//on load, generate a new array of shuffled indexes to fetch quotes from quotesArr:
componentDidMount() {
let shuffleIdxs = () => {
let order = [];
for (let i = 0; i < quotesArr.length; i++) { order.push(i) };
for (let i = order.length - 1; i > 0; i--) {
let j = Math.floor(Math.random() * (i + 1));
[order[i], order[j]] = [order[j], order[i]];
}
return order;
}
//fill order array with shuffle indexes:
this.setState({
order: shuffleIdxs(),
quoteCount: 0
});
}
getNewQuote() {
this.setState(state => ({
quoteCount: state.quoteCount + 1
}))
}
render() {
//this works; shows the quotes in the original order, as quoteCount increases:
//let quote = '"' + quotesArr[this.state.quoteCount].quote + '"';
//this doesn't work and throws error:
let quote = '"' + quotesArr[this.state.order[this.state.quoteCount]].quote + '"';
let author = quotesArr[this.state.quoteCount].author;
let from = quotesArr[this.state.quoteCount].from ? ', ' + quotesArr[this.state.quoteCount].from : ''; //display quotesArr's 'from' key value if present
return (
<div id="quote-box">
<p id="text">{quote}</p>
<p id="author">{author}<em>{from}</em></p>
<p>quote count: {this.state.quoteCount};</p>
<p>order: {this.state.order[this.state.quoteCount]}</p>
<div className="buttons-div">
<button>
{/* href="twitter.com/intent/tweet" passes the test but doesn't work. The following works: https://twitter.com/share?ref_src=twsrc%5Etfw */}
<a id="tweet-quote" href="twitter.com/intent/tweet" target="_blank" data-show-count="false">Tweet</a><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</button>
<button id="new-quote" onClick={this.getNewQuote}>New Quote</button>
</div>
</div>
)
}
}
function App() {
return (
<div className="App">
<ReactFCCtest />
<header className="App-header">
<h1>Stellar quotes machine</h1>
</header>
<QuoteBox />
</div>
);
}
export default App;