I’m trying to create a quizlet-learn kind of app, and I have multiple instances of Card components. I have it set so when I pick an answer on one of the cards, it updates the state and display based on what I picked. There are buttons at the bottom to change the card. The issue is when I pick an answer on a card, the state is updated for every card component and showAnswer
is set to true. How can I prevent this from happening and make it only update the same card?
My card component:
export default class Card extends React.Component {
constructor(props) {
super(props);
this.state = {
option_correct: Math.random() > 0.5,
showAnswer: false,
optionPicked: 0
}
}
handleClick(optionPicked) {
console.log(this.state.showAnswer);
console.log(this.props.prompt + ' 1');
if (!this.props.hidden) {
if (!this.state.showAnswer)
this.setState({
optionPicked: optionPicked
});
this.setState({
showAnswer: true
});
}
}
handleKeyPress(event) {
console.log(prompt + ' 2');
if (event.key === 'Enter') {
this.props.onFinish();
event.preventDefault();
}
}
render() {
console.log(this.props.prompt + ' ' + this.state.showAnswer);
return (
<div className={`card ${this.state.showAnswer ? "show_answer" : ""}`} onKeyDown={this.handleKeyPress}>
<div className='prompt'>
{this.props.prompt}
</div>
<small className={'continue'}>
Press Enter to Continue...
</small>
<div className='options'>
<button className={'option ' +
(this.state.option_correct ? 'correct' : 'wrong')
+ ' ' + (this.state.optionPicked === 1 ? 'picked' : 'not_picked')} onClick={() => {
this.handleClick(1);
}}>
{this.state.option_correct ? this.props.answer : this.props.wrongAnswer}
</button>
<button className={'option ' + (this.state.option_correct ? 'wrong' : 'correct')
+ ' ' + (this.state.optionPicked === 2 ? 'picked' : 'not_picked')} onClick={() => {
this.handleClick(2);
}}>
{this.state.option_correct ? this.props.wrongAnswer : this.props.answer}
</button>
</div>
</div>
);
}
}
My card container component:
class CardData {
constructor(prompt, answer, wrongAnswer) {
this.prompt = prompt;
this.answer = answer;
this.wrongAnswer = wrongAnswer;
}
}
export default function Cards() {
const [flashcarddata, setFlashcarddata] = useState([]);
const [current, setCurrent] = useState(0);
useEffect(() => {
setFlashcarddata([
new CardData('word1', 'correct', 'incorrect'),
new CardData('word2', 'correct 2', 'incorrect 2'),
new CardData('word3', 'correct 23', 'incorrect 23')
])
}, []);
const cards = flashcarddata.map((card, index) => {
return <Card
prompt={card.prompt}
answer={card.answer}
wrongAnswer={card.wrongAnswer}
hidden={current !== index}
onFinish={() => {
console.log('finished ' + card.prompt);
nextCard();
}}
/>;
});
function previousCard() {
setCurrent(current - 1);
}
function nextCard() {
setCurrent(current + 1);
}
const loading = <div className="loading">Loading card...</div>;
return (
<div>
{flashcarddata && flashcarddata.length > 0 ? cards[current] : loading}
<div className="nav">
{current > 0 ? (
<button onClick={previousCard}>Previous card</button>
) : (
<button className="disabled" disabled>
Previous card
</button>
)}
{current < flashcarddata.length - 1 ? (
<button onClick={nextCard}>Next card</button>
) : (
<button className="disabled" disabled>
Next card
</button>
)}
</div>
</div>
);
}
So far I’ve tried to change Card into a class from a function component, make the handleClick
method only work if the card was the one being displayed, and changed from having every card being rendered and having most of them set display: block
in css to having just one card rendered at a time.