I have seen similar questions but none of the answers are working in my case and I hope someone will be able to tell me why.
My ReactApp renders 3 card components that flip when clicked on. The cards are populated with data from an object array and is rendered with a map function (added info in case it has an impact). Here is parent component.
import React from 'react'
import FlipCard from './FlipCard'
const cards = [
{
id: 1,
text: 'NOPE',
},
{
id: 2,
text: '!!WINNER!!',
},
{
id: 3,
text: 'NOPE',
},
]
const shuffleCards = array => {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1))
const temp = array[i]
array[i] = array[j]
array[j] = temp
}
return array
}
shuffleCards(cards)
console.log(cards)
const CardGameUI = () => {
shuffleCards(cards)
return (
<div className="cards-ui">
{cards.map(card => (
<FlipCard key={card.id} text={card.text} value={card.id} />
))}
</div>
)
}
export default CardGameUI
When one of the cards are flipped, I need the onClick for the other cards to be disabled. I tried using state and a conditional in my onClick event but it has no effect. The according to the console.log, the state of the play boolean is changed and if I manually change the conditional in the onCLick event check if play is true, then it works perfectly fine. I am clearly missing something because it seems as though the conditional is working and the state is changing.
import React, { useState } from 'react'
import ReactCardFlip from 'react-card-flip'
import FrontComponent from './FrontComponent'
import BackComponent from './BackComponent'
const FlipCard = ({ text, value }) => {
const [isFlipped, setIsFlipped] = useState(false)
const [activeCard, setActiveCard] = useState(2)
const [play, setPlay] = useState(false)
console.log(play.valueOf())
function handleFlip() {
setPlay(true)
setIsFlipped(!isFlipped)
console.log(isFlipped)
setActiveCard(value)
console.log(value)
}
if (activeCard !== 2) {
console.log('Play again?')
}
return (
<>
<ReactCardFlip isFlipped={isFlipped} flipDirection="horizontal">
<FrontComponent onClick={!play ? handleFlip : null} />
<BackComponent text={text} value={value} />
</ReactCardFlip>
</>
)
}
export default FlipCard
What am I missing?
You should manage the onClick
event and the flip
state on the parent instead of inside the card.
An high-level overview will be:
const CardGameUI = () => {
const [flipped, setFlipped] = useState({});
const hasFlipped = Object.values(flipped).includes(true);
const handleFlip = id => () => setFlipped(flipped => ({
...flipped,
[id]: true // can be changed to toggle in case you need it in the future
}));
return (
<div>
{cards.map(({ id, text }) => (
<FlipCard
key={id}
text={text}
value={id}
onFlip={handleFlip(id)}
flipped={flipped[id]}
disabled={hasFlipped}
/>
))}
</div>
)
};
const FlipCard = ({ text, value, onFlip, flipped , disabled}) => {
return (
<ReactCardFlip isFlipped={flipped} flipDirection="horizontal">
<FrontComponent onClick={onFlip} disabled={disabled} />
<BackComponent text={text} value={value} />
</ReactCardFlip>
)
}