React allows you to take imperative code, and turn it into a declarative and reusable component. You can see here in our componentDidMount(), we're adding an event listener to the window beforeUnload.
This is an event that is fired when the window is tried to close, so that we can potentially alert our user that there's unsaved changes. To make this reusable, we'll first create another class. The class will be called beforeUnload.
In our render function, we'll return react.children.only(this.props.children). What this will do is ensure that only a single child is being returned or passed in. Then if there is more than one child being passed in, it will warn us.
We'll then go take some code that we've already in our componentDidMount(), and our componentWillUnmount(). We'll add them to our new component. We'll now also need to get our alert message. We'll add it to our new component as well.
Because we'll be referencing this inside of our alert message, we'll also have to set up a constructor, pass in our props, call super. Then this.alertMessage equals this.alertMessage.bind(this). Now, we want the respond to the active flag that we pass in, we can add an if statement.
Say if this.props.active, and place this inside of here. Any time we're passing in a truthy value, this will be executed. We can't just return and assign return value, this.props.active, because in some browsers, any time you assign anything here or return anything, it will be active, even if sometimes this is undefined or null.
It just depends on the browser, so this is an easier way to provide cross-browser compatibility. Now, we're ready to use our component. First, we need to go remove this.alertMessage, because we moved it to our other component.
Then rather than this div, we can replace it with beforeUnload. Then we can also pass in our active equals this.state.active. See here we have a button with an onclick. This will then call a toggle, and toggle our active state, and just give us a little indicator whether we're active or inactive.
With this active, rather than a true or false, you might have editing, or you might have whatever else. As long as you're passing in a truthy value, the user will be alerted that they have something that needs to be fixed on the page before the page closes.
Now, let's check it out in the browser. See here, we have our app with our active button. If we try to close our app, you can see that it asks us to stay or leave. In our case, we'll click stay. If we then click active again, it'll switch it to inactive.
Now, if we try to close our window, because we're passing in a falsey value, it will allow us to close the window without actually popping up the confirmation message.
Now, using an if statement like we have here in alertMessage might work in our case of beforeUnload, but there might be times where you need to actually figure out whether or not you need to remove the function attachment or add the function attachment.
What we'll do is use componentDidUpdate() to figure that out. componentDidUpdate() will receive our previous props, and also have access to the current props. What we need to do is destructure active from our current props.
Then we'll destructure active, and just call it wasActive, from our previous props. Now, we can write an if statement. If it was active before, and it's not active now, which means it went from true to false, that means we want to remove our event listener.
However, if it wasn't active, and it's active now, that means it previously wasn't active, but now it is, that we should attach our event listener. Now, one other important note to make is that in our componentWillUnmount(), we must always call removeEventListener and remove the function that we're attaching it to.
Otherwise, when this component gets unmounted right here, when this potentially disappears, we will still have a function attached to the window. That means we'll have a memory leak.