Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
a custom react hook that I want feedback on because it feels like a lot of work and maybe I'm missing something...
// Feedback requested on the useDeepCompareEffect
// it just feels like a bit of work...
// when people use the useQuery hook, they'll typically
// do so like this: `useQuery(myQuery, {var1: props.value})`
// which means that passing `variables` to `useEffect` will
// trigger a rerun of the callback even if they didn't
// actually change (referrential equality)
function useQuery({query, variables}) {
() => {
// make a request with the query and variables
[query, variables],
// more stuff goes here...
function useDeepCompareEffect(callback, inputs) {
const previousInputs = usePrevious(inputs)
const inputsAreEqual = _.isEqual(inputs, previousInputs)
// every time our effect callback runs, the cleanup
// function for the effect will change. If we don't
// actually call the callback, then the user's cleanup
// function wont be updated. So we'll keep track of the
// most recent cleanup function and return that if
// we don't actually call the callback.
const cleanupRef = useRef()
() => {
if (!inputsAreEqual) {
cleanupRef.current = callback()
return cleanupRef.current
// run the effect callback if equality changes
// this can change from [true] to [false]
// or from [false] to [true]
// both changes will cause the callback to re-run
// which is why we have the `if (!inputsAreEqual)`
// condition above.
function usePrevious(value) {
const ref = useRef()
useEffect(() => {
ref.current = value
return ref.current
// P.S. if you ask me what font/theme this is, what editor it is,
// or how I made this screenshot... I'm not going to answer.
// -->
Copy link

cdock1029 commented Nov 9, 2018

import isEqual from 'react-fast-compare'

function useQuery(params) {
  const [cachedParams, setCachedParams] = useState(params)
  const [data, setData] = useState()

  // ok to update the state during rendering, like "getDerivedStateFromProps"
  if (!isEqual(cachedParams, params)) {

    () => {
        const {query, variables} = cachedParams
        // make a request with the query and variables
        // setData(data)
  return data

Copy link

kentcdodds commented Feb 7, 2019

I think this is the proper solution actually:

function useDeepCompareMemoize(value) {
  const ref = React.useRef()

  if (!_.isEqual(value, ref.current)) {
    ref.current = value

  return ref.current

function useDeepCompareEffect(callback, dependencies) {
  React.useEffect(callback, useDeepCompareMemoize(dependencies))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment