Tom Granot
Tom Granot

Reputation: 1850

Passing props to handler function

I'm following Pure React, and there's a House component that needs some building (omitted the imports for brevity):

class House extends React.Component {

    state = {
        bathroom: true,
        bedroom: false,
        kitchen: true,
        livingRoom: false
    }

    flipSwitch = (action) => {
        this.setState({
            ???????????????
        });
    }

    render () {
        return (
            <>
            <RoomButton room='kitchen' handler={this.flipSwitch}/>
            <RoomButton room='bathroom' handler={this.flipSwitch}/>
            <RoomButton room='livingRoom' handler={this.flipSwitch}/>
            <RoomButton room='bedroom' handler={this.flipSwitch}/>
            </>
        );
    }
}

const RoomButton = ({room, handler}) => (
    <button onClick={handler}>
        {`Flip light in ${room}!`}
    </button>
)

ReactDOM.render (
    <House/>,
    document.getElementById('root')
)

Desired outcome: when you click the <room> button, the state of the House component changes to reflect the flipping of the lightswitch in the room (i.e. true is light on, false is light off).

I'm wondering what should go instead of the ????? - how do I pass the room prop into the handler function from inside a given RoomButton component?

Tried just passing it in, and got a Maximum depth reached error from React.

ES6 answers would be most appreciated, BTW.

Upvotes: 0

Views: 611

Answers (2)

Jeff Hechler
Jeff Hechler

Reputation: 285

Try this

flipSwitch = (room, action) => {
    this.setState((prevState) => ({
        [room]: !prevState[room]
    }));
}

const RoomButton = ({room, handler}) => (
    <button onClick={handler.bind(null, room)}>
        {`Flip light in ${room}!`}
    </button>
)

The .bind(null, room) line essentially preloads the handler function with one of the arguments, in this case room. This is called currying. I left action in the flipSwitch parameters list in case you had plans for it, but it's unused currently.

Upvotes: 3

Olivier Boiss&#233;
Olivier Boiss&#233;

Reputation: 18113

You can try this solution :

the flipSwitch will accept the room name as parameter and will update the state using a callback (in order to retrieve the right value of the current state)

 class House extends React.component {
 ....

   flipSwitch = room => {
     this.setState(state => ({
        [room]: !state[room]
     });
   }

 ...
 }


const RoomButton = ({room, handler}) => (
  <button onClick={() => handler(room)}>
    {`Flip light in ${room}!`}
  </button>
);

Upvotes: 5

Related Questions