Urql: Updating `res.fetching` doesn't trigger Context consumer updates

Created on 12 Oct 2019  ·  6Comments  ·  Source: FormidableLabs/urql

Describe the bug

Hi folks! Big fan of Urql here. In the update to 1.6.0, interaction between useQuery and the React Context API stopped working in the same way. Here's the relevant code (pulled out from my own project, codesandbox link below):

// viewer-context.tsx

export const ViewerContext = createContext<ViewerContextValue>({
  fetching: true,
  viewer: null
})

export function ViewerProvider({ children }: { children: ReactNode }) {
  const [res] = useQuery<{ viewer: User | null }>({
    query: viewerQuery
  })

  const value = {
    fetching: res.fetching,
    viewer: res.data && res.data.viewer ? res.data.viewer : null
  }

  return (
    <ViewerContext.Provider value={value}>{children}</ViewerContext.Provider>
  )
}
// Main.tsx, which consumes that context using `useContext`

export default function Main() {
  const { viewer, fetching } = useContext(ViewerContext)
  console.log(fetching)

  // Still loading
  if (fetching) return null

  return <h1>Hi!</h1>
}

I'm able to reliably reproduce differing behavior between 1.5.1 and 1.6.0. In the former, when res.fetching changes, consumers of the context are updated (the console.log in Main.tsx follows the updates). That is not the behavior I'm seeing in 1.6.0 - the Context API checks for object equality using Object.is, so I'm guessing something has changed there (presumably in #447)? That doesn't really make sense, but updating urql is the only change I've made while testing this out.

In setting up the below codesandbox, I've realized that maybe using a Context for not repeating the same query is unnecessary thanks to urql's caching - I'd love your opinion there, but either way I'm bringing this up as a likely unintentional regression in 1.6.0!

Steps to reproduce

A codesandbox link (thanks for the template below!): https://codesandbox.io/embed/urql-issue-template-client-vj73c

Expected behavior

I'd expect consumers of a Context that sets a value using res.fetching to correctly update consumers of the context.

Actual behavior

The value is updated in the provider itself, but not in the consumers. You can toggle between 1.5.1 and 1.6.0 in the Codesandbox link to see it in action!

Thanks! Let me know how I can help ❤️

bug 🐛

All 6 comments

This is indeed very odd! 🤔

I’ve checked the CodeSandbox and the parent component with useQuery seems to be updating reliably — after a while I’m seeing res.fetching === true there.

But this update somehow doesn’t trigger a context change, although a new context value is created on every render. Instead the change seems to be swallowed and the child never receives the update.

Ok, I was able to reproduce this on react-wonka in isolation, so I should be able to figure out how to fix this. This kind of seems like a weird edge-case, since the component with useStreamValue (in the case of urql, useQuery) does update correctly. https://github.com/kitten/react-wonka/pull/1

Edit: okay, I found the issue, although I'm not sure what React specifically is doing here. I'm just glad that it'll be fixed 😆

@kitten can we get new patch release, i have similar problem

The hotfix has been merged and 1.6.1 has been published. Also verified that it's fixed here: https://codesandbox.io/s/urql-issue-template-client-6sbwx

@JasonEtco Nice catch! :tada: And thanks for reporting it this promptly with such a nice reproduction 🙏

Amazing, that was so fast! ⚡️⚡️⚡️ Thank you for the quick fix @kitten ❤️ I've confirmed that 1.6.1 works as expected in my project!

@kitten thanks for the quick fix, working great now ^^

Was this page helpful?
0 / 5 - 0 ratings

Related issues

capaj picture capaj  ·  5Comments

ivosequeros picture ivosequeros  ·  5Comments

wodnjs6512 picture wodnjs6512  ·  3Comments

dotansimha picture dotansimha  ·  4Comments

TLadd picture TLadd  ·  4Comments