Search code examples
reactjsreact-routerreact-apolloreact-lifecycle

Remove items from the database on leaving or closing the page from a React Component


I have a React component that is part of a React/Apollo Booking app. I store all the bookings in a SQL database that is hooked up with React-Apollo in between. Before the customer starts the payment process the database is sent temporary bookings to "hold" certain times and restrain other customers from booking the same time. And if a customer refreshes/leave the page I wanna remove those temp bookings from the Apollo DB.

The work flow goes like:

  1. Select times to book(and here I add the booking to the DB).
  2. List the customers bookings for review and add extra features.
  3. Payment process

So the issue I have is that if a customer leaves on step 2, then I want to remove those booking from the DB. Can this be done like with the code below or do I need put like a timer on these temp bookings and remove after certain time from the DB if certain criteria is not met?

I have read several topics on the subject and tryed suggested solutions. I am guessing the call to the DB is asynchorone or the fact that props are involved are the issue and that is why it's not working.

componentDidMount() {
    window.addEventListener('beforeunload', function () {
      this.props.tempBookings.forEach(booking => {
        removeBookingFromDB(booking.id)
      })
    }, false);
  }

  componentWillUnmount() {
    window.addEventListener('beforeunload', function () {
      this.props.tempBookings.forEach(booking => {
        removeBookingFromDB(booking.id)
      })
    }, false)
  }

Solution

  • The function you provide as a callback for the beforeunload event is not bound to this. Use an arrow function instead:

    window.addEventListener('beforeunload', () => {
        this.props.tempBookings.forEach(booking => {
            removeBookingFromDB(booking.id)
        })
    }, false);
    

    To correctly remove the listener on unmount you need to bind the handler to the component instance so that you can reference it in componentWillUnmount:

    class MyComponent extends React.Component {
    
        // must be an arrow function
        removeBookings = () => {
            this.props.tempBookings.forEach(booking => {
                removeBookingFromDB(booking.id)
            })
        }
    
        componentDidMount() {
            window.addEventListener('beforeunload', this.removeBookings, false);
        }
    
        componentWillUnmount() {
            window.removeEventListener('beforeunload', this.removeBookings, false)
        }
    }