Skip to content

Instantly share code, notes, and snippets.

@kjellski
Last active April 27, 2020 12:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kjellski/42ae99e7b1d85a76d835274c255c6af0 to your computer and use it in GitHub Desktop.
Save kjellski/42ae99e7b1d85a76d835274c255c6af0 to your computer and use it in GitHub Desktop.
Workarround for `pollInterval` with `@apollo/react-hooks/useQuery`
// NOTE: not using poll here because the interval needs to change on every call.
// So we're using multiple hooks to achieve this:
// 1. `useInterval` to keep the recalculation with `setVariablesIntervalCallback` triggering
// 2. `useState` to have a clear state change when we called `setVariablesIntervalCallback`
// 3. `usePrevious` to have data while new data is beeing fetched so the table can stay intact
const Container = ({ children, someValue }) => {
const [variables, setVariables] = useState({
someValue,
value: calculateValue(),
})
const setVariablesIntervalCallback = useCallback(() => {
setVariables(variables => ({
...variables,
value: calculateValue(),
}))
}, [setVariables])
useInterval(setVariablesIntervalCallback, POLL_INTERVAL_IN_MS)
const { data, loading, error } = useErrorHandlingQuery(
queryHubViewDashboard,
{
skip: !hubId,
variables,
},
)
const previousData = usePrevious(data)
return children({
// we only want the last fetched data if there's no new one, this is helping while refetching to still fill the UI
data: data || previousData,
loading,
error,
})
}
import { useRef, useEffect } from 'react'
/**
* A hook to repeatedly execute a `callback` after `intervalInMs` passed
* @param callback function to be executed
* @param intervalInMs interval to repeat the call at
* @returns {null}
*/
export const useInterval = (callback, intervalInMs) => {
const savedCallback = useRef()
useEffect(() => {
savedCallback.current = callback
}, [callback])
useEffect(() => {
if (intervalInMs) {
const handler = (...args) => savedCallback.current(...args)
const id = setInterval(handler, intervalInMs)
return () => {
if (id) {
clearInterval(id)
}
}
}
}, [callback, intervalInMs])
return null
}
import { useEffect, useRef } from 'react'
/**
* A hook to have access to whatever the previous value was.
* For example:
* <pre>
* // State value and setter for our example
* const [count, setCount] = useState(0);
*
* // Get the previous value (was passed into hook on last render)
* const prevCount = usePrevious(count);
*
* // Display both current and previous count value
* return (
* <div>
* <h1>Now: {count}, before: {prevCount}</h1>
* <button onClick={count => setCount(count + 1)}>Increment</button>
* </div>
* );
* </pre>
*
* Also, see:
* <a href="https://usehooks.com/usePrevious/">https://usehooks.com/usePrevious</a>
*
* @param value
* @returns {*} previous value
*/
export const usePrevious = value => {
// The ref object is a generic container whose current property is mutable ...
// ... and can hold any value, similar to an instance property on a class
const ref = useRef()
// Store current value in ref
useEffect(() => {
ref.current = value
}, [value]) // Only re-run if value changes
// Return previous value (happens before update in useEffect above)
return ref.current
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment