Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing a method down two levels

I'm trying to build a simple little game for fun, but I'm hitting a stump when it comes to passing this method down to its grandchildren. I've found similar topics, but none that answered my question. For this question, I've managed to narrow the code down to what the problem is perceived to be.

The relevant component structure is App.js > Runeboard.js > Rune.js

The Goal: To have Rune.js have an onClick function on each rune that is dynamically produced by whatever is in this.state.usersRunes.

I don't believe there is anything wrong with the function itself, or passing it down as props, because console logging the runes values all succeed when in Runeboard.js, and even in Rune.

This works, but is not dynamic to what is in the this.state.usersRunes array:

      return (
            <div>
                Runeboard
                <span onClick={() => this.props.activateRune(this.props.usersRunes[0])}> {this.props.usersRunes[0]} </span>
                <span onClick={() => this.props.activateRune(this.props.usersRunes[1])}> {this.props.usersRunes[1]} </span>
                <span onClick={() => this.props.activateRune(this.props.usersRunes[2])}> {this.props.usersRunes[2]} </span>
                <span onClick={() => this.props.activateRune(this.props.usersRunes[3])}> {this.props.usersRunes[3]} </span>
                <br />
                <br />
            </div>
        );

The problem with that, is I'd like for every item in this.state.usersRunes (an array of integers), a Rune component that has its own onClick that successfuly executes activateRune with its parameter of the value of the rune. (The value of the rune being this.state.usersRunes So this.state.usersRunes = [2,3,5,9] the values would be 2, 3, 5, and 9.


So even though the above works, this does not and I do not understand why:

App.js The activateRune function:

    activateRune(rune) {
        if (this.state.inBet || this.state.mustBet) {
            this.call(rune)
        } else if (!this.state.inBet) {
            this.setMessage("You cannot place a rune first!")
        }
    }

App.js render:

                <Runeboard
                    activateRune={this.activateRune}
                    usersRunes={this.state.usersRunes}
                />

Runeboard.js render:

        let rune = this.props.usersRunes.map((rune, i) => {
            console.log(rune) // this works and successfully prints the array's integers
            return(
                <div>
                    <Rune activateRune={this.props.activateRune} 
runeValue={rune} key={i} />
                </div>
            )
        })

        return(
            <div>
                {rune}
            </div>
        )

Rune.js render:

        return (
            <div onClick={() => this.props.activateRune(this.props.runeValue)}>
                {this.props.runeValue} // this works and successfully displays the value
            </div>
        );

How can I resolve this?

like image 860
bananabrann Avatar asked Mar 22 '19 00:03

bananabrann


People also ask

What does it mean to lift the state up?

In React, sharing state is accomplished by moving it up to the closest common ancestor of the components that need it. This is called “lifting state up”.

What does the React createElement() method return?

createElement() Create and return a new React element of the given type. The type argument can be either a tag name string (such as 'div' or 'span' ), a React component type (a class or a function), or a React fragment type.

What is a PureComponent React?

A React component is considered pure if it renders the same output for the same state and props. For this type of class component, React provides the PureComponent base class. Class components that extend the React. PureComponent class are treated as pure components.


1 Answers

I think it might be an issue with your syntax.

<div onClick={() => {this.props.activateRune(rune)}}>

If you use curly braces, {}, you need a return value:

<div onClick={() => {return this.props.activateRune(rune)}}>

You can also avoid the curly braces and have it be:

<div onClick={() => this.props.activateRune(rune)}>

like image 153
shanemacbride Avatar answered Nov 15 '22 00:11

shanemacbride