Multi-page app - page events

On a page within a multi-page app, I'm using Pusher to update the app in realtime. But when the user navigates away from the page, I need to remove those listeners.

My issue is I can't find anything to trigger some code when the user changes pages in a multi-page app. So when they navigate away the listeners are still active and cause errors to be shown to the user.

Example code:

window.pusher = new Pusher('pusher-key-here');
window.pusherChannel = window.pusher.subscribe('my-channel');

window.pusherChannel.bind('InterpretedOrderUpdated', function(data) {
  retoolQuery.trigger();
});

So the above all works, but when the user navigates to a different page (and an event is pushed) it'll try to run retoolQuery.trigger(). This variable is still defined, but retool throws an error message "retoolQuery is not a valid query. Did you delete it or rename it?"

I'd be happy with that failing silently too - I've turned off all error notifications on the query and at the app level. But I think that error message comes from somewhere else, rather than the query.

I just need to remove my listeners when the page changes, but I'm struggling to do that.

Any help / advice / different ways of doing this would be appreciated.

Hi @arron,

How are you navigating between apps? If you are using the navigation component, you can attach an additional event handler on click to remove these listeners.

Here is a screenshot of the event handler that is added by default to navigation components in multipage apps, which handles switching to the selected page:


Hi Erin

Thanks for getting back to me. I have thought about this approach, and also running a script on each of the other pages. I think that would work, but it's not ideal;

  • I'll probably forget somewhere to do this
  • In the future, I'm going to need different pages to use different event listeners. So it'll get messy trying to clean up the correct ones.

I thought about using the Custom React component, I thought that'd be a nice and clean way to do this. I came up with this:

import React, { useEffect } from 'react'
import { type FC } from 'react'

import { Retool } from '@tryretool/custom-component-support'

export const MountUnmount: FC = () => {
  const onMount = Retool.useEventCallback({ name: 'onMount' })
  const onUnmount = Retool.useEventCallback({ name: 'onUnmount' })

  useEffect(() => {
    onMount()
    return () => {
      onUnmount()
    }
  }, [])

  return <div>Mount / Unmount (hide this)</div>
}

But the unmount is never fired, when the component is removed from Retool I'm guessing it's done in a way that React can't cleanup like normal?

Is there any other way I can use the above to do something when the component is destroyed?

Thanks again!

1 Like

Just another update - I've been able to resolve this by building Pusher into the custom component. We can then expose the event data back to Retool and trigger an event on the Retool side too.

When the component is destroyed all the connections are cleaned up as they are now within the component itself.

Thanks for your help!