tomwassing
tomwassing

Reputation: 961

Why does State remains unchanged after setState

I am trying to show/hide a modal when a user clicks on a item inside a list. The modal shows up as planned but cannot be hidden. When _dismiss() is called, setState executes but when I console.log the state inside the callback, the parameter show is still true.

Why is this happening?

Message.jsx

export default class Message extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            show: false
        };

        this._onClick = this._onClick.bind(this);
        this._dismiss = this._dismiss.bind(this);
    }

    _onClick(e) {
        e.preventDefault();
        this.setState({
            show: true
        })
    }

    _dismiss() {
        this.setState({
            show: false
        }, function () {
            console.log(this.state) // logs: Object {show: true}
        })
    }

    render() {
        return (
            <div onClick={this._onClick} className="message">
                <Modal show={this.state.show} close={this._dismiss}>
                    <h1>...</h1>
                </Modal>
            </div>
        );
    }
}

Modal.jsx

export default class Modal extends React.Component {
    constructor(props) {
        super(props);

        this._onClose = this._onClose.bind(this);
    }

    _onClose() {
        this.props.close()
    }

    render() {
        if (this.props.show) {
            return (
                <div className="modal" onClick={this._onClose} >
                    <div className="content">
                        {this.props.children}
                    </div>
                </div>
            );
        } else {
            return null
        }
    }
}

Upvotes: 0

Views: 205

Answers (1)

powerc9000
powerc9000

Reputation: 2103

The div is still getting on onClick events event when its children are clicked. I suspect _dismiss is being called and then _onClick is being called. React batches setState calls so it ends up setting show back to true.

Remedies.

If the close callback of handler give you the event as an argument. Call e.stopPropagation() or From @richsilv in the comments e.stopImmediatePropagation().

Or if it doesn't pass the event. Check in the _onClick if show is true or false. If it is true, don't setState

Upvotes: 3

Related Questions