Skip to content

Commit a996443

Browse files
committed
optimistic updates, learn mutations
1 parent 5c688c0 commit a996443

File tree

3 files changed

+45
-6
lines changed

3 files changed

+45
-6
lines changed

README.md

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ Polling is paused when the window lose focus. To fix that issue we can set `refe
6565

6666
Combine polling with callbacks. Use the `refetchInterval` option to pull the api data every 3 seconds. Behind the scenes add a fourth superhero of your choice to the superheroes array in `db.json`.
6767

68-
a.) Within the onSuccess callback check if the number of heroes is 4 and ifit is the case I want you to stop the polling.
69-
b.) Within the onError callback I want you to stop the polling.
68+
a) Within the onSuccess callback check if the number of heroes is 4 and ifit is the case I want you to stop the polling.
69+
b) Within the onError callback I want you to stop the polling.
7070

7171
Hint:
7272
Mantain state variable whose initial value is 3000. State variable will be assigned to `refetchInterval` configuration. In callbacks check for the response / errors and set the state variable to false.
@@ -83,9 +83,9 @@ In our example we transformed data to be an array of just heroes names instead o
8383

8484
We can query by id in two ways (look commits under branch name: `feature/12-queryById`).
8585

86-
a.) Solution 1 or first commit: **QueryById with manuali passed ID**
86+
a) Solution 1 or first commit: **QueryById with manuali passed ID**
8787
- We can manually pass id into fetch function: file `useSuperHeroData`
88-
b.) Solution 2 or second commit: **QueryById with react-query automatic passed id**
88+
b) Solution 2 or second commit: **QueryById with react-query automatic passed id**
8989
- React query automatically pass id into fetch function: file `useSuperHeroData`
9090

9191
**9. react-query - Parallel queries**
@@ -108,6 +108,15 @@ If we add flag `keepPreviousData` into the useQuery options, when we paginate to
108108

109109
Handling mutation response will save you additional network request.
110110

111+
**14. react-query - Optimistic updates**
112+
Updating the state before performing a mutation under the assumption that nothing can go wrong.
113+
114+
`onMutate:` is called before the mutation function is fired and is passed the same variables that mutation function would receive.
115+
a) Cancel any outgoing refetches so they don't override our optimistic update.
116+
b) Get a hold of the current query data before we make any update. This will help us role back in case the mutation fails.
117+
`onError:` is called if the mutation encounters an error.
118+
`onSettled:` is called if the mutation is either successfull or encounters an error. `invalidateQueries` will ensure client state is in sync with server state. The user will not notice a difference.
119+
111120
## Available Scripts
112121

113122
In the project directory, you can run:

db.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@
4444
"name": "Test",
4545
"alterEgo": "Test",
4646
"id": 9
47+
},
48+
{
49+
"name": "hello",
50+
"alterEgo": "world",
51+
"id": 10
4752
}
4853
],
4954
"friends": [

src/lib/hooks/useSuperHeroesData.tsx

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,38 @@ export const useSuperHeroesData = ({ onSuccess, onError }: Props) => {
2525
export const useAddSuperHeroData = () => {
2626
const queryClient = useQueryClient()
2727
return useMutation(addSuperHero, {
28-
onSuccess: (response) => {
28+
// onSuccess: (response) => {
29+
// queryClient.setQueryData('super-heroes', (oldQueryData: any) => {
30+
// return {
31+
// ...oldQueryData,
32+
// data: [...oldQueryData.data, response.data],
33+
// }
34+
// })
35+
// },
36+
onMutate: async (newHero) => {
37+
await queryClient.cancelQueries('super-heroes')
38+
const previousHeroData = queryClient.getQueryData('super-heroes')
2939
queryClient.setQueryData('super-heroes', (oldQueryData: any) => {
3040
return {
3141
...oldQueryData,
32-
data: [...oldQueryData.data, response.data],
42+
data: [
43+
...oldQueryData.data,
44+
{
45+
id: oldQueryData.data.length + 1,
46+
...newHero,
47+
},
48+
],
3349
}
3450
})
51+
return {
52+
previousHeroData,
53+
}
54+
},
55+
onError: (_error, _hero, context: any) => {
56+
queryClient.setQueryData('super-heroes', context.previousHeroData)
57+
},
58+
onSettled: () => {
59+
queryClient.invalidateQueries('super-heroes')
3560
},
3661
})
3762
}

0 commit comments

Comments
 (0)