Solution Part 3
Let us bring in React Query
Let us look at the code with the problem highlighted:
- The
fetchProfile
andsaveProfile
functions are imported from theapi
module. - But we still make raw API call in the
useEffect
hook and in thehandleSave
function. - We also have to worry about errors, loading state, etc.
- In fact, we are missing a lot of other things too like caching, retrying, etc.
Handling the above issues is really difficult, and that is where React Query
comes into the picture. An industry standard library for handling data-fetching.
Install React Query
Next, we have to setup the QueryClient
in our main.tsx
(the higher the component tree, the higher the context) file:
Query and Mutation
We can now use useQuery
and useMutation
hooks to fetch and mutate data.
useQuery
Let us log the result of the useQuery
hook in the App
component.
So, your query works as expected. But we still have to worry about the errors, loading state, etc. But useQuery
handles all of that for us.
For now, we also comment out the handler for the handleSave
function to avoid any TS errors.
Fetching is handled by the useQuery
hook. What about the update? We can use the useMutation
hook to handle the update.
useMutation
But there is a problem, our data is not updated in the UI. But the network request is successful. This is after the mutation, we have to let queryClient
know that the data has been update and it needs to be refetched. That is what the queryKey
is for.
Remember to keep the query keys unique. Using the same key for different queries can cause unexpected behavior.
Separating Concerns
We can further separate the UI from the business logic.
We will move the useQuery
and useMutation
hooks to the features/profile
folder. We will create new files called use-profile.ts
and use-update-profile-mutation.ts
in the features/profile
folder. These will hold the custom hooks for fetching and updating the profile.
Now we can import them into App.tsx
More Clean Code
Our handleSave
and the respective mutation does not need to be in the App
component, we can move it to the ProfileForm
component.
We also set the disabled
attribute on the Save
button based on the isPending
state.
We update the ProfileDisplay
component to use the onEnableEditMode
prop to limit the access to the edit mode.
One final refactor
The form currently does not use a form
. Let us also do some quick client side validation before saving the data.
At this point, your code should be a good match to the branch of the repository: 1-solution-part-3
Last updated on