website icon indicating copy to clipboard operation
website copied to clipboard

Stacks RPC code example

Open jwhits opened this issue 1 year ago • 2 comments

The hono stacks page showing RPC react example with posts and gets is really useful showing how hono and RPC with tanstack query can be used for frontend and backend.

However to get the example working I had to change the way the mutation worked by adding mutationFN. Could be worth updating the page?

Current code example

const mutation = useMutation<
    InferResponseType<typeof $post>,
    Error,
    InferRequestType<typeof $post>['form']
  >(
    async (todo) => {
      const res = await $post({
        form: todo,
      })
      return await res.json()
    },
    {
      onSuccess: async () => {
        queryClient.invalidateQueries({ queryKey: ['todos'] })
      },
      onError: (error) => {
        console.log(error)
      },
    }
  )

Changed to

const mutation = useMutation<
    InferResponseType<typeof $post>,
    Error,
    InferRequestType<typeof $post>['form']
  >({
    // Mutation function
    mutationFn: async (todo) => {
      const res = await $post({
        form: todo,
      });
      return await res.json()
    },

    // Success handler
    onSuccess: async () => {
      queryClient.invalidateQueries({ queryKey: ['todos'] })
    },

    // Error handler
    onError: (error: Error) => {
      console.error(error)
    },
  })

jwhits avatar May 04 '24 05:05 jwhits

Another thing worth noting, is that with the example in the docs, the onError callback doesn't seem to be triggered when the API throws.

Even when there is a 400 or 500 in the API, the onSuccess is still called. The onle way I was able to make it work, was by throwing inside the mutationFn, like so:

const mutation = useMutation<
    InferResponseType<typeof $post>,
    Error,
    InferRequestType<typeof $post>['form']
  >({
    // Mutation function
    mutationFn: async (todo) => {
      const res = await $post({
        form: todo,
      });

      // Only by throwing here, the onError is called
      if(!res.ok) throw new Error()

      return await res.json()
    },

    // Success handler
    onSuccess: async () => {
      queryClient.invalidateQueries({ queryKey: ['todos'] })
    },

    // Error handler
    onError: (error: Error) => {
      console.error(error)
    },
  })

@usualoma could you share some insights on why this is?

fidalgodev avatar Aug 26 '24 15:08 fidalgodev