Deepanshu Arora
Deepanshu Arora

Reputation: 435

Event handler not accessing the correct value from redux state

In my web application, I want to prompt user when he/she tries to close the browser/tab based upon Redux state using event handlers.

I am using the below code to prompt user before exiting based upon 'isLeaving' state.

function mapStateToProps(state) {
    const {isLeaving} = state.app.getIn(['abc']);
    return {
        isLeaving
    };
}

@connect(mapStateToProps, {}, undefined, {withRef: true})
export default class MyClass extends React.component {
    @autobind
    stayOnPage(event) {
        if (this.props.isLeaving) {
            const message = 'Are you sure you want to leave';
            event.returnValue = message;
            return message;
        }
        return false;
    }

    componentDidMount() {
        window.addEventListener('beforeunload', (event) => {
            this.stayOnPage(event);
        });
    }

    componentWillUnmount() {
        window.removeEventListener('beforeunload', (event) => {
            this.stayOnPage(event);
        });
    }



    componentWillReceiveProps(nextProps) {
        if (this.props.prop1 !== nextProps.prop2) {
           // do something
        }
    }

    render() {
       //
    }
}

This code works fine. But whenever there is a change in prop1, I see that this.props.isLeaving does not have updated value.

Can somebody help? What is I'm doing wrong here?

Upvotes: 0

Views: 836

Answers (2)

Peter Hurst
Peter Hurst

Reputation: 106

You aren't cleaning up correctly in componentWillUnmount. The event handler you're trying to remove is a brand new function closure, not the same instance that you added. You should just attach the actual handler, rather than using an arrow function, like so:

componentDidMount() {
    window.addEventListener('beforeunload', this.stayOnPage);
}

componentWillUnmount() {
    window.removeEventListener('beforeunload', this.stayOnPage);
}

Possibly what you are seeing is the event triggering on a stale component instance, so it has old state.

Upvotes: 1

Robbie Milejczak
Robbie Milejczak

Reputation: 5770

React uses synthetic events, basically events are recycled to be more performant. You can read more on that here

What I normally do is pass the value I need on invocation

Not sure if this will work in your specific case because I define my event handlers in JSX instead of accessing the window object (which you might want to do as well but to be honest I'm not sure) but I use this pattern all the time to handle e.target.value properly

Upvotes: 0

Related Questions