The problem: I'm using Apollo Client, and have the deck rendered like this "/deck/2" and I want to randomly shuffle the cards, and display just one at a time with a button to view the next. I keep running in the problem with React re-rendering everytime the state is changed (my onClick index counter +1), which reshuffles the cards since the shuffledCards variable is inside the query. I'm not sure how to prevent this from happening.
How can I shuffle the list without worrying about them being reshuffled 'onClick' of the button. I imagine there is a way to get the randomized array outside of the render, which I can do in Regular react, but using Apollo queries I'm stumbling to understand.
This is where I am stumbling due to my inexperience in React and Graphql with Apollo, and I haven't found a similar Apollo graphql project to lean off of. I can't use map on an object, but maybe there is a way to use map to display 1 object of the array at a time? I haven't found a working solution.
What I intend to have happen: I simply want to render the shuffled array of cards one at a time, and pressing the next button should step through the cards in the randomized array, without re-rendering whenever I click the button, otherwise cards will be repeated at random.
Here's the code:
import React, { Component, Fragment } from "react";
```
import CardItem from "./CardItem";
const CARDS_QUERY = gql`
query CardsQuery($id: ID!) {
```
`;
export class Cards extends Component {
constructor(props) {
super(props);
this.state = {
index: 0
};
this.goToNext = this.goToNext.bind(this);
}
goToNext() {
this.setState({
index: this.state.index + 1
});
}
shuffle(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
return array;
}
render() {
let { id } = this.props.match.params;
id = parseInt(id);
return (
<Fragment>
<Query query={CARDS_QUERY} variables={{ id }}>
{({ data, error, loading }) => {
if (loading) {
return <Loading />;
}
if (error)
}
const CardsToRender = data.deck.cards;
//This variable gets reshuffled at every re-render
const shuffledCards = this.shuffle(CardsToRender);
//Single item to be returned
const item = shuffledCards[this.state.index];
if (this.state.index >= shuffledCards.length) {
return (
<div>
<h1>Finished</h1>
</div>
);
} else {
return (
<Fragment>
// Here I can get one item to display, but if I press next, the state changes which fires a re-render,
//shuffling the cards once more. My intention is to only shuffle cards at first render until the browser page is
//refreshed or user navigates away
<h1>{item.front}</h1>
<h1>{item.back}</h1>
//My second attempt is to map out the cards, but I have only been able to render a list,
// but not one at a time. Maybe there is a simple code solution in my .map to display
//one at a time without needing to change state?
{shuffledCards.map(card => (
<CardItem key={card.id} card={card} />
))}
<p>
<button onClick={this.goToNext}>Next</button>
</p>
</Fragment>
);
}
}}
</Query>
</Fragment>
);
}
}
```
I'll be grateful for any help provided. Thank you!