startPolling and stopPolling in redwood cells

I want to be able to poll some of our pages, but it keeps on polling, if you minimize the browser/change the tab.
It would be nice to be able to suspense it.

One idea for that wolud be to use apollo and startPolling/stopPolling Queries - Apollo GraphQL Docs

Is there any way to use this with redwood (or cells in general) to start/stop polling when a window is minimized/in the background?

HI @razzeee from the docs I read,

startPolling
(interval: number) => void
A function that instructs the query to begin re-executing at a specified interval (in milliseconds).

I’d try to se if that function startPolling could be using the the beforeQuery setting and they have some flag effect that sets if minimized or some other event and then call stopPoilling?

See beforeQuery here Cells | RedwoodJS Docs where you can set those like:

export const beforeQuery = (props) => {
  return {
    variables: props,
    fetchPolicy: 'cache-and-network',
    startPolling: () => console.log('startPolling'),
    stopPolling: () => console.log('stopPolling'),
  }
}

If you find a nice pattern, a PR to the Cell docs for this would be much appreciated! Thanks!

Some quick Googling found this example:

const { loading, error, data, startPolling, stopPolling } = useQuery(GET_DELIVERIES_QUERY)

 useEffect(() => {
     startPolling(5000)
   return () => {
    stopPolling()
   }
 }, [startPolling, stopPolling])

But, understand that Cells abstract the useQuery.

That said, those should be available in Success component:

As far as I can tell beforeQuery doesn’t do anything with start/stop polling?

export const beforeQuery = (props: any) => {
  console.log('props', props)
  return {
    variables: props,
    startPolling: (interval: number) => console.log('startPolling', interval),
    stopPolling: () => console.log('stopPolling'),
  }
}

And it would be kinda cool to have the suspend logic in the cell, but I don’t think we can set props from the Success and have them read in beforeQuery, so we’ll probably need to do that above and handle the window a bit like this:


  useEffect(() => {
     if (document.visibilityState === 'visible') {
       startPolling(5000)
     } else {
       stopPolling()
     }
   }, [document.visibilityState])

  return (
    <>
      <MyCell
        otherVars={id}
        startPolling={startPolling}
        stopPolling={endPolling}
      />
    </>
  )

Not sure if I misunderstand, but startPolling is undefined in success it seems?

export const Success = ({
  other
  startPolling,
  stopPolling,
}) => {
console.log(startPolling)
...
}

Should I open an issue for this?

Hey @razzeee,

I think you’re looking for startPolling inside queryResult.

So…

export const Success = ({
  queryResult
}) => {
console.log(queryResult)
queryResult.startPolling()
...
}

HTH,
Danny

Hey danny, that seems to work, with a bit more on top. Unfortunately it’s not perfect I guess.

I need to do this in the page above the Cell that’s going to poll:


const MyPage = ({ id }: MyPageProps) => {
  const { t } = useTranslation()
  const documentVisible = useVisibilityChange() // https://usehooks.com/usevisibilitychange

  const [pollingState, setPollingState] = useState<'start' | 'stop'>('start')

  useEffect(() => {
    if (documentVisible === true) {
      console.log('on')
      setPollingState('start')
    } else {
      console.log('off')
      setPollingState('stop')
    }
  }, [documentVisible])

  return (
    <>
      <MetaTags title={t('title')} description={t('my-page')} />

      <MyCell selectedProject={id} pollingState={pollingState} />
    </>
  )
}

Then in the cell

export const Success = ({
  queryResult,
  pollingState,
}: CellSuccessProps<MyQuery, MyQueryVariables>) => {
  pollingState === 'start'
    ? queryResult.startPolling(5000)
    : queryResult.stopPolling()

I think it’s still doing another refresh, when you switch away from the page, but it at least stops then after it.