useUpdateCharacter.js 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. // noinspection JSIgnoredPromiseFromCall
  2. export const useUpdateCharacter = defineMutation(() => {
  3. const queryCache = useQueryCache()
  4. // noinspection JSUnusedLocalSymbols
  5. const { mutate, ...mutation } = useMutation({
  6. onMutate({ id, updates, optimisticUpdates }) {
  7. if (optimisticUpdates) {
  8. // save the current character and character list
  9. const oldCharacterList = queryCache.getQueryData(characterListQuery.key)
  10. // find the index of the mutated character
  11. const characterIndex = _findIndex(oldCharacterList, { id })
  12. let oldOptions, oldCharacter, newCharacter, newCharacterList
  13. if (characterIndex >= 0) {
  14. // save the options and character
  15. oldOptions = queryCache.getQueryData(characterOptionsQuery.key)
  16. oldCharacter = oldCharacterList[characterIndex]
  17. // create the new character
  18. newCharacter = { ...oldCharacter, ...updates }
  19. // create a copy of the character list with the updated character
  20. newCharacterList = oldCharacterList.toSpliced(characterIndex, 1, newCharacter)
  21. // calculate new character options
  22. const newOptions = getCharacterOptions(newCharacterList)
  23. // update caches
  24. queryCache.setQueryData(characterListQuery.key, newCharacterList)
  25. queryCache.setQueryData(characterOptionsQuery.key, newOptions)
  26. // cancel (without refreshing) queries depending on the character
  27. queryCache.cancelQueries({ key: characterListQuery.key })
  28. queryCache.cancelQueries({ key: characterByIdQuery(id).key })
  29. }
  30. // pass the old and new character, and character lists to the other hooks
  31. return {
  32. oldCharacter,
  33. newCharacter,
  34. oldCharacterList,
  35. newCharacterList,
  36. oldOptions
  37. }
  38. }
  39. },
  40. mutation: ({ id, updates, optimisticUpdates = true }) =>
  41. useEmit("character:update", id, updates),
  42. onSettled(_data, _error, { id, optimisticUpdates }, { newCharacter }) {
  43. // invalidate the queries to refetch the new data
  44. if (!optimisticUpdates || newCharacter) {
  45. queryCache.invalidateQueries({ key: characterListQuery.key })
  46. queryCache.invalidateQueries({ key: characterByIdQuery(id).key })
  47. }
  48. },
  49. onError(
  50. error,
  51. { id, optimisticUpdates },
  52. { oldCharacter, oldCharacterList, oldOptions, newCharacterList }
  53. ) {
  54. // before applying the rollback, check if the values in the cache are the same
  55. // in case the cache was updated by another mutation or query
  56. if (
  57. optimisticUpdates &&
  58. newCharacterList === queryCache.getQueryData(characterListQuery.key)
  59. ) {
  60. queryCache.setQueryData(characterListQuery.key, oldCharacterList)
  61. queryCache.setQueryData(characterOptionsQuery.key, oldOptions)
  62. queryCache.setQueryData(characterByIdQuery(id).key, oldCharacter)
  63. }
  64. // handle the error
  65. console.error("[useUpdateCharacter] [onError]", error)
  66. },
  67. onSuccess() {}
  68. })
  69. return {
  70. ...mutation,
  71. updateCharacter: (id, updates) => mutate({ id, updates, optimisticUpdates: true }),
  72. updateCharacterFromEvent: (id, updates) => mutate({ id, updates, optimisticUpdates: false })
  73. }
  74. })