Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Customise the .unwrap implementation #4395

Open
HHK1 opened this issue May 6, 2024 · 0 comments
Open

Customise the .unwrap implementation #4395

HHK1 opened this issue May 6, 2024 · 0 comments

Comments

@HHK1
Copy link
Contributor

HHK1 commented May 6, 2024

Context

I'm using RTK Query, and plugging it onto an existing project.

HTTP Errors from the API are some specific subclass of Error. They may contain some extra information returned by the backend, and the specific subclass is used in the codebase to narrow down the type of error with syntax such as:

 try {
    // Do a request
 } catch (error) {
  if (error instance of AuthError) {
    // do something like log out
  } else if (error instance of ServerError) {
    // Show a 500 hundred like error
  } else if (error instance of ClientError {
   // More specific error handling
  }
}

I've written a serializeError to be able to throw a serialised version of those errors inside my queryFn used in my api endpoints definitions. (I don't use the baseQuery, but it's probably not super relevant).

I was able to write a custom unwrapResponse function that takes a query or mutation result and extract the data from it, or throw an error with the correct class instance (based on the content of the serialised error inside the result). That way I don't have to rewrite the error handling logic across the whole application.

A typical usage of a mutation that requires error handling would look like this:

  const [createTeam] = useCreateTeamMutation()

  const onSubmit = handleSubmit(async ({ name, pictureUrl }) => {
    try {
      const result = await createTeam({ name, pictureUrl })
      const team = unwrapResult(result)
      onSuccess(team)
    } catch (error) {
      const errorInfo = getErrorInfo(error) // this function checks if the error has a specific subclass
      setError(errorInfo)
    }
  })

Problem

Every time I use a query or a mutation other developers in the team must know about my custom unwrapReponse function, and if they don't they may incorrectly use the existing .unwrap function on the query / mutation result. Doing so won't raise any error, and errors thrown from that .unwrap won't be handled properly (those errors will be serialised errors, and not the expected subclass instances)

A typical bad usage of the same mutation will become:

  const [createTeam] = useCreateTeamMutation()

  const onSubmit = handleSubmit(async ({ name, pictureUrl }) => {
    try {
      const team = await createTeam({ name, pictureUrl }).unwrap()
      onSuccess(team)
    } catch (error) {
      const errorInfo = getErrorInfo(error) // Here the `getErrorInfo` will fail and will swallow the exact error that was thrown
      setError(errorInfo)
    }
  })

So my question is:

I'm wondering if there is a way to customise that .unwrap method, and pass my custom unwrapResponse implementation to avoid exposing a "bad" unwrap implementation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant