'How can I call a function from the parent component with an event in the child?

I'm busy learning React and one of the tasks is building a game where the cards shuffle on each try. The card array and the shuffle method are in a parent component (I use map to render the cards), but the retry button is in the child component.

I've read almost 20 StackOverflow questions and many docs, but somehow my logic is simply not working.

Can someone please help me to get this to work.

Parent:

import React from 'react'
import FlipCard from './FlipCard'

const cards = [
    {
        id: 1,
        text: 'NOPE',
    },
    {
        id: 2,
        text: `!!WIN-
        NER!!`,
    },
    {
        id: 3,
        text: 'NOPE',
    },
]

const shuffle = 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
}

const shuffleCards = shuffle(cards)

const CardGameUI = () => {
    return (
        <div className="cards-ui">
            {cards.map(card => (
                <FlipCard
                    key={card.id}
                    text={card.text}
                    value={card.id}
                    shuffleCards={shuffleCards}
                />
            ))}
        </div>
    )
}

export default CardGameUI

Child:

import React from 'react'
import ReactCardFlip from 'react-card-flip'
import FrontComponent from './FrontComponent'
import BackComponent from './BackComponent'
import RetryModal from './RetryModal'

class FlipCard extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            isFlipped: false,
            gamesPlayed: 0,
            gamesWon: 0,
            gamesLost: 0,
            show: false,
            gameMsg: '',
        }

        this.handleFlip = this.handleFlip.bind(this)
        this.handleShow = this.handleShow.bind(this)
        this.handleClose = this.handleClose.bind(this)
        this.handleReset = this.handleReset.bind(this)
        this.handleRetry = this.handleRetry.bind(this)
    }

    handleReset() {
        this.setState({
            isFlipped: false,
            gamesPlayed: 0,
            gamesWon: 0,
            gamesLost: 0,
            show: false,
            gameMsg: '',
        })
        this.props.shuffleCards
    }

    handleRetry() {
        this.setState({
            isFlipped: false,
            show: false,
            gameMsg: '',
        })
        this.props.shuffleCards
    }

    handleClose() {
        this.setState({
            show: false,
        })
    }
    handleShow() {
        this.setState({
            show: true,
        })
    }

    handleFlip() {
        this.setState({
            isFlipped: true,
            gamesPlayed: +1,
            show: false,
        })

        if (this.props.value !== 2) {
            this.setState({
                gamesLost: 0,
                gameMsg:
                    'It looks like you lost this round. Want to play another?',
            })
        } else if (this.props.value === 2) {
            this.setState({
                gamesWon: 0,
                gameMsg: 'CONGRATULATIONS!!!. Want to win again?',
            })
        }

        setTimeout(() => {
            this.handleShow()
        }, 1000)
    }

    render() {
        const text = this.props.text
        const value = this.props.value
        const isFlipped = this.state.isFlipped

        return (
            <>
                <ReactCardFlip isFlipped={isFlipped} flipDirection="horizontal">
                    <FrontComponent onClick={this.handleFlip} />

                    <BackComponent text={text} value={value} />
                </ReactCardFlip>

                <RetryModal
                    handleShow={this.handleShow}
                    handleClose={this.handleClose}
                    handleReset={this.handleReset}
                    handleRetry={this.handleRetry}
                    show={this.state.show}
                    text={this.state.gameMsg}
                />
            </>
        )
    }
}

export default FlipCard

I included all the code from these two components as I wasn't sure what will help clarify.

Essentially the shuffleCards method needs to run when handleReset and handleRetry are triggered.



Solution 1:[1]

let array = [...cards];
const shuffle = () => {
    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
}

Just replace shuffle function by this code ! I hope it works !

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Hritik Sharma