Просмотр исходного кода

use pinia-colada-plugin-normalizer api for optimistic updates

Jason Gorst 3 недель назад
Родитель
Сommit
343fb56ca5

+ 8 - 83
app/mutations/characters/useCreateCharacter.js

@@ -1,96 +1,21 @@
-// noinspection JSIgnoredPromiseFromCall
+import { updateQueryData } from "pinia-colada-plugin-normalizer"
 
 export const useCreateCharacter = defineMutation(() => {
-  const queryCache = useQueryCache()
 
-  // noinspection JSUnusedLocalSymbols
   const { mutate, ...mutation } = useMutation({
-    onMutate({ character, optimisticUpdates }) {
-      if (optimisticUpdates) {
-        // save the current character list and options
-        const oldCharacterList = queryCache.getQueryData(characterListQuery.key)
-        const oldOptions = queryCache.getQueryData(characterOptionsQuery.key)
+    mutation: ({ character }) => useEmit("character:create", character),
+    onError: (error) => console.error("[useCreateCharacter] [onError]", error),
 
-        // create the new character
-        const newCharacter = {
-          ...character,
-          id: Number.MAX_SAFE_INTEGER
-        }
+    onSuccess: (character) => {
+      const optionsCache = useOptionsCache()
 
-        console.log("[useCreateCharacter] [onMutate]", newCharacter)
-
-        // create a copy of the current character list with the new character
-        const newCharacterList = [...oldCharacterList || [], newCharacter]
-
-        // calculate new character options
-        const newOptions = getCharacterOptions(newCharacterList)
-
-        // update the caches with the new character list, options, and character
-        queryCache.setQueryData(characterListQuery.key, newCharacterList)
-        queryCache.setQueryData(characterOptionsQuery.key, newOptions)
-
-        // cancel (without refreshing) queries depending on the character list
-        queryCache.cancelQueries({ key: characterListQuery.key })
-
-        // pass the old and new character list, options,  and the new character to the other hooks
-        return { oldCharacterList, newCharacterList, oldOptions, newCharacter }
-      }
-    },
-
-    mutation: ({ character, optimisticUpdates = true }) => {
-      console.log("[useCreateCharacter] [mutation]", character)
-
-      return useEmit("character:create", character)
-    },
-
-    // on both error and success
-    onSettled(_data, _errors, { optimisticUpdates }, { newCharacter }) {
-      console.log("[useCreateCharacter] [onSettled]")
-
-      if (optimisticUpdates) {
-        // invalidate queries to refetch the new data
-        queryCache.invalidateQueries({ key: characterListQuery.key })
-
-        // newCharacter can be undefined if the onMutate hook fails
-        if (newCharacter) {
-          // directly cancel queries with a temp id and remove cache entry
-          queryCache.getEntries({ key: characterByIdQuery(newCharacter.id).key, exact: true })
-            .map((entry) => {
-              queryCache.cancel(entry)
-              queryCache.remove(entry)
-            })
-        }
-      }
-    },
-
-    onError(error, { optimisticUpdates }, { oldCharacterList, newCharacterList, oldOptions }) {
-      // before applying the rollback, check if the value in the cache is the same
-      //    in case the cache was updated by another mutation or query
-      if (optimisticUpdates && newCharacterList === queryCache.getQueryData(characterListQuery.key)) {
-        console.log("[useCreateCharacter] [onError] [rollback]")
-
-        queryCache.setQueryData(characterListQuery.key, oldCharacterList)
-        queryCache.setQueryData(characterOptionsQuery.key, oldOptions)
-      }
-
-      // handle the error
-      console.error("[useCreateCharacter] [onError]", error)
-    },
-
-    onSuccess(character, { optimisticUpdates }, { oldCharacterList }) {
-      console.log("[useCreateCharacter] [onSuccess]", character)
-
-      if (optimisticUpdates) {
-        // create a copy of oldCharacterList with newly returned character
-        const characterList = [...oldCharacterList || [], character]
-        queryCache.setQueryData(characterListQuery.key, characterList)
-      }
+      updateQueryData(characterListQuery.key, (data) => [...data, character])
+      optionsCache.update()
     }
   })
 
   return {
     ...mutation,
-    createCharacter: (character) => mutate({ character, optimisticUpdates: true }),
-    createCharacterFromEvent: (character) => mutate({ character, optimisticUpdates: false })
+    createCharacter: (character) => mutate({ character })
   }
 })

+ 14 - 54
app/mutations/characters/useDeleteCharacter.js

@@ -1,72 +1,32 @@
-// noinspection JSIgnoredPromiseFromCall
+import { useOptimisticUpdate } from "pinia-colada-plugin-normalizer"
 
 export const useDeleteCharacter = defineMutation(() => {
-  const queryCache = useQueryCache()
+  const { transaction } = useOptimisticUpdate()
 
-  // noinspection JSUnusedLocalSymbols
   const { mutate, ...mutation } = useMutation({
-    onMutate({ id, optimisticUpdates }) {
-      if (optimisticUpdates) {
-        // save the current character list, and options
-        const oldCharacterList = queryCache.getQueryData(characterListQuery.key)
+    onMutate({ id }) {
+      const optionsCache = useOptionsCache()
+      const tx = transaction()
+      tx.remove("character", _toString(id))
+      optionsCache.update()
 
-        // find the index of the deleted character
-        const characterIndex = _findIndex(oldCharacterList, { id })
-
-        let oldOptions, oldCharacter, newCharacterList
-
-        if (characterIndex >= 0) {
-          // save the options and character
-          oldOptions = queryCache.getQueryData(characterOptionsQuery.key)
-          oldCharacter = oldCharacterList[characterIndex]
-
-          // create a copy of the current character list without the deleted character
-          const newCharacterList = _reject(oldCharacterList || [], { id })
-
-          // calculate new character options
-          const newOptions = getCharacterOptions(newCharacterList)
-
-          // update caches
-          queryCache.setQueryData(characterListQuery.key, newCharacterList)
-          queryCache.setQueryData(characterOptionsQuery.key, newOptions)
-
-          // cancel (without refreshing) queries depending on the character
-          queryCache.cancelQueries({ key: characterListQuery.key })
-          queryCache.cancelQueries({ key: characterByIdQuery(id).key })
-        }
-
-        // pass the id and the old and new character lists to the other hooks
-        return { oldCharacter, oldCharacterList, newCharacterList, oldOptions }
-      }
+      return { ...tx, rollbackOptions: optionsCache.rollback }
     },
 
-    mutation: ({ id, optimisticUpdates = true }) => useEmit("character:delete", id),
-
-    onSettled(_data, _error, { id }) {
-      // invalidate the queries to refetch the new data
-      queryCache.invalidateQueries({ key: characterListQuery.key })
-      queryCache.invalidateQueries({ key: characterByIdQuery(id).key })
-    },
+    mutation: ({ id }) => useEmit("character:delete", id),
 
-    onError(error, { id, optimisticUpdates }, { oldCharacter, oldCharacterList, oldOptions, newCharacterList }) {
-      // before applying the rollback, check if the values in the cache are the same
-      //    in case the cache was updated by another mutation or query
-      if (optimisticUpdates && newCharacterList === queryCache.getQueryData(characterListQuery.key)) {
-        queryCache.setQueryData(characterListQuery.key, oldCharacterList)
-        queryCache.setQueryData(characterOptionsQuery.key, oldOptions)
-        queryCache.setQueryData(characterByIdQuery(id).key, oldCharacter)
-      }
+    onError: (error, _vars, { rollback, rollbackOptions }) => {
+      rollback?.()
+      rollbackOptions()
 
-      // handle the error
       console.error("[useDeleteCharacter] [onError]", error)
     },
 
-    onSuccess() {}
+    onSuccess: (_data, _vars, { commit }) => commit?.()
   })
 
   return {
     ...mutation,
-    deleteCharacter: (id) => mutate({ id, optimisticUpdates: true }),
-    deleteCharacterFromEvent: (id) => mutate({ id, optimisticUpdates: false })
+    deleteCharacter: (id) => mutate({ id })
   }
 })

+ 14 - 73
app/mutations/characters/useUpdateCharacter.js

@@ -1,91 +1,32 @@
-// noinspection JSIgnoredPromiseFromCall
+import { useOptimisticUpdate } from "pinia-colada-plugin-normalizer"
 
 export const useUpdateCharacter = defineMutation(() => {
-  const queryCache = useQueryCache()
+  const { transaction } = useOptimisticUpdate()
 
-  // noinspection JSUnusedLocalSymbols
   const { mutate, ...mutation } = useMutation({
-    onMutate({ id, updates, optimisticUpdates }) {
-      if (optimisticUpdates) {
-        // save the current character and character list
-        const oldCharacterList = queryCache.getQueryData(characterListQuery.key)
+    onMutate: ({ id, updates }) => {
+      const optionsCache = useOptionsCache()
+      const tx = transaction()
+      tx.set("character", _toString(id), updates)
+      optionsCache.update()
 
-        // find the index of the mutated character
-        const characterIndex = _findIndex(oldCharacterList, { id })
-
-        let oldOptions, oldCharacter, newCharacter, newCharacterList
-
-        if (characterIndex >= 0) {
-          // save the options and character
-          oldOptions = queryCache.getQueryData(characterOptionsQuery.key)
-          oldCharacter = oldCharacterList[characterIndex]
-
-          // create the new character
-          newCharacter = { ...oldCharacter, ...updates }
-
-          // create a copy of the character list with the updated character
-          newCharacterList = oldCharacterList.toSpliced(characterIndex, 1, newCharacter)
-
-          // calculate new character options
-          const newOptions = getCharacterOptions(newCharacterList)
-
-          // update caches
-          queryCache.setQueryData(characterListQuery.key, newCharacterList)
-          queryCache.setQueryData(characterOptionsQuery.key, newOptions)
-
-          // cancel (without refreshing) queries depending on the character
-          queryCache.cancelQueries({ key: characterListQuery.key })
-          queryCache.cancelQueries({ key: characterByIdQuery(id).key })
-        }
-
-        // pass the old and new character, and character lists to the other hooks
-        return {
-          oldCharacter,
-          newCharacter,
-          oldCharacterList,
-          newCharacterList,
-          oldOptions
-        }
-      }
+      return { ...tx, rollbackOptions: optionsCache.rollback }
     },
 
-    mutation: ({ id, updates, optimisticUpdates = true }) =>
-      useEmit("character:update", id, updates),
-
-    onSettled(_data, _error, { id, optimisticUpdates }, { newCharacter }) {
-      // invalidate the queries to refetch the new data
-      if (!optimisticUpdates || newCharacter) {
-        queryCache.invalidateQueries({ key: characterListQuery.key })
-        queryCache.invalidateQueries({ key: characterByIdQuery(id).key })
-      }
-    },
+    mutation: ({ id, updates }) => useEmit("character:update", id, updates),
 
-    onError(
-      error,
-      { id, optimisticUpdates },
-      { oldCharacter, oldCharacterList, oldOptions, newCharacterList }
-    ) {
-      // before applying the rollback, check if the values in the cache are the same
-      //    in case the cache was updated by another mutation or query
-      if (
-        optimisticUpdates &&
-        newCharacterList === queryCache.getQueryData(characterListQuery.key)
-      ) {
-        queryCache.setQueryData(characterListQuery.key, oldCharacterList)
-        queryCache.setQueryData(characterOptionsQuery.key, oldOptions)
-        queryCache.setQueryData(characterByIdQuery(id).key, oldCharacter)
-      }
+    onError: (error, _vars, { rollback, rollbackOptions }) => {
+      rollback?.()
+      rollbackOptions()
 
-      // handle the error
       console.error("[useUpdateCharacter] [onError]", error)
     },
 
-    onSuccess() {}
+    onSuccess: (_data, _vars, { commit }) => commit?.()
   })
 
   return {
     ...mutation,
-    updateCharacter: (id, updates) => mutate({ id, updates, optimisticUpdates: true }),
-    updateCharacterFromEvent: (id, updates) => mutate({ id, updates, optimisticUpdates: false })
+    updateCharacter: (id, updates) => mutate({ id, updates })
   }
 })