-
Notifications
You must be signed in to change notification settings - Fork 5.3k
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
feat(frontend): Utilize TanStack Query #5096
Conversation
const response = await fetch("/api/submit-feedback", { | ||
method: "POST", | ||
body: JSON.stringify(data), | ||
body: JSON.stringify(feedback), | ||
headers: { | ||
"Content-Type": "application/json", | ||
Authorization: `Bearer ${token}`, | ||
}, | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not use the request
helper which does the token plumbing for us? I don't like the idea of passing token
around the app--it adds a lot more plumbing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Our current request handler is quite messy. A major concern is how request
does error handling. TanStack Query already manages error by catching thrown errors, but the request
handler introduces its own error-handling logic. This complicates integration with TanStack Query and also makes custom error handling more difficult.
IMO retrieving the token from local storage would no longer be ideal. Our updated auth context now manages the token state (to address the improper retrieval of tokens via local storage throughout the app), and we use the useAuth
context hook within the custom query hooks that call the request function. Basically very similar to what request
tried to do but this better follows React principles and keeps the code more consistent and maintainable.
Final note is that request
breaks some practice by introducing any
types and ignores some eslint rules
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can come back to this if we really want to, just probably create or heavily patch the existing request
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall LGTM. I'd like @mamoodi do do a small QA run on this branch given how much is changing though
End-user friendly description of the problem this fixes or functionality that this introduces
Maintaining fetch logic, such as caching and handling requests through React Router's data loaders, can introduce complexity and make the code harder for others to understand.
Give a summary of what the PR does, explaining any non-trivial design decisions
Use TanStack Query for improved cache management and better handling of client-side request context. Favor React hooks over data loaders.
General Pattern
For queries
A basic implementation of a query would look something like this:
You can read more about the basics here: https://tanstack.com/query/latest/docs/framework/react/guides/queries
For better reusability and readability, we wrap it within a custom hook:
Example usage:
For mutations
Similarly, we wrap the mutation within a hook:
One thing to note are the available mutation side effects (
onError
). You can read more about them here: https://tanstack.com/query/latest/docs/framework/react/reference/useMutationExample usage:
The same callback functions are provided to the
mutate
function, though caution the order of execution. Read more here: https://tanstack.com/query/latest/docs/framework/react/guides/mutations#mutation-side-effectsCaching behaviour
By default, cache time (
gcTime
) is set to 5 minutes and stale time (staleTime
) is set to 0.gcTime
staleTime
Basic example
You can read more here: https://tanstack.com/query/latest/docs/framework/react/guides/caching
The only case where I changed the defaults is for the
useIsAuthed
hook (for authenticating):Changelog
useQuery
anduseMutation
hooks in place of regular requests made in data loadersrequests
function,useQuery
anduseMutation
already handle error and success cases more elegantly<fetcher.Form>
and<Form>
that call to action resource routes and handle them with custom submit handlersWe previously relied on loaders and actions to manage state across the app. Since retiring them, we now need to use appropriate hooks and contexts. Additionally, directly accessing localStorage is considered a bad practice because there's no reliable way to "subscribe" to changes. This approach conflicts with React's re-rendering lifecycle, leading to outdated or inconsistent data. Any logic that causes side effects or requires maintaining state should be migrated to a hook or a context to ensure proper synchronization and reactivity.
AuthContextProvider
accessible via theuseAuth
hook that maintainstoken
andghToken
states as well as persist them inlocalStorage
UserPrefsProvider
accessible via theuseUserPrefs
hook that handles changes in settings and whether its up-to-dateclearSession
with a newuseEndSession
hook that resets some state and navigates back to homeTo run this PR locally, use the following command: