Blitz: Optimistic UI updates

Created on 5 Jun 2020  路  5Comments  路  Source: blitz-js/blitz

When using @apollo/react-hooks, I have the possibility to provide an optimistic response: https://www.apollographql.com/docs/react/performance/optimistic-ui/

When looking into how mutations (functions) are used with Blitz: https://github.com/blitz-js/blitz/blob/canary/USER_GUIDE.md#using-mutations

It doesn't seem like that's supported yet. Is something like that planned?

kinfeature-change scopcore statudone

Most helpful comment

Yes, we can support this!

Currently we have mutate that works like this:

export default function (props: {query: {id: number}}) {
  const [product, {mutate}] = useQuery(getProduct, {where: {id: props.query.id}})
  return (
    <Formik
      initialValues={product}
      onSubmit={async (values) => {
        try {
          const product = await updateProduct(values)
          mutate(product)
        } catch (error) {
          alert("Error saving product")
        }
      }}>
      {/* ... */}
    </Formik>
  )
}

We can add an option to mutate to disable the automatic refetch which would enable optimistic updates like this:

export default function (props: {query: {id: number}}) {
  const [product, {mutate}] = useQuery(getProduct, {where: {id: props.query.id}})
  return (
    <Formik
      initialValues={product}
      onSubmit={async (values) => {
        try {
          // Update local cache without triggering refetch
          mutate(values, {refetch: false})
          const product = await updateProduct(values)
          // Update local cache with result, then refetch
          mutate(product)
        } catch (error) {
          // Set cache back to original result, then refetch
          mutate(product)
          alert("Error saving product")
        }
      }}>
      {/* ... */}
    </Formik>
  )
}

What do you think?

All 5 comments

Yes, we can support this!

Currently we have mutate that works like this:

export default function (props: {query: {id: number}}) {
  const [product, {mutate}] = useQuery(getProduct, {where: {id: props.query.id}})
  return (
    <Formik
      initialValues={product}
      onSubmit={async (values) => {
        try {
          const product = await updateProduct(values)
          mutate(product)
        } catch (error) {
          alert("Error saving product")
        }
      }}>
      {/* ... */}
    </Formik>
  )
}

We can add an option to mutate to disable the automatic refetch which would enable optimistic updates like this:

export default function (props: {query: {id: number}}) {
  const [product, {mutate}] = useQuery(getProduct, {where: {id: props.query.id}})
  return (
    <Formik
      initialValues={product}
      onSubmit={async (values) => {
        try {
          // Update local cache without triggering refetch
          mutate(values, {refetch: false})
          const product = await updateProduct(values)
          // Update local cache with result, then refetch
          mutate(product)
        } catch (error) {
          // Set cache back to original result, then refetch
          mutate(product)
          alert("Error saving product")
        }
      }}>
      {/* ... */}
    </Formik>
  )
}

What do you think?

I really like that! The possibility to not refetch automatically should be there anyways imo.

I can jump on the task if we decide to implement it :)

@eliasjohansson ok this is all yours if you want it!

@eliasjohansson Did you start on this in the end? I just found this issue while thinking about doing optimistic UI and added the flag Brandon suggested to try it out. It seems to work nicely. If you've not started on this already I could try adding some tests to this tomorrow and submit a PR. What do you think?

@shaunchurch Unfortunately I havent. Haven't had much time over recently. You're free to take it over or whatever you feel like doing :)

Was this page helpful?
0 / 5 - 0 ratings