useCreateCharacter.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. // noinspection JSIgnoredPromiseFromCall
  2. export const useCreateCharacter = defineMutation(() => {
  3. const queryCache = useQueryCache()
  4. // noinspection JSUnusedLocalSymbols
  5. const { mutate, ...mutation } = useMutation({
  6. onMutate({ character, optimisticUpdates }) {
  7. if (optimisticUpdates) {
  8. // save the current character list and options
  9. const oldCharacterList = queryCache.getQueryData(characterListQuery.key)
  10. const oldOptions = queryCache.getQueryData(characterOptionsQuery.key)
  11. // create the new character
  12. const newCharacter = {
  13. ...character,
  14. id: Number.MAX_SAFE_INTEGER
  15. }
  16. console.log("[useCreateCharacter] [onMutate]", newCharacter)
  17. // create a copy of the current character list with the new character
  18. const newCharacterList = [...oldCharacterList || [], newCharacter]
  19. // calculate new character options
  20. const newOptions = getCharacterOptions(newCharacterList)
  21. // update the caches with the new character list, options, and character
  22. queryCache.setQueryData(characterListQuery.key, newCharacterList)
  23. queryCache.setQueryData(characterOptionsQuery.key, newOptions)
  24. // cancel (without refreshing) queries depending on the character list
  25. queryCache.cancelQueries({ key: characterListQuery.key })
  26. // pass the old and new character list, options, and the new character to the other hooks
  27. return { oldCharacterList, newCharacterList, oldOptions, newCharacter }
  28. }
  29. },
  30. mutation: ({ character, optimisticUpdates = true }) => {
  31. console.log("[useCreateCharacter] [mutation]", character)
  32. return useEmit("character:create", character)
  33. },
  34. // on both error and success
  35. onSettled(_data, _errors, { optimisticUpdates }, { newCharacter }) {
  36. console.log("[useCreateCharacter] [onSettled]")
  37. if (optimisticUpdates) {
  38. // invalidate queries to refetch the new data
  39. queryCache.invalidateQueries({ key: characterListQuery.key })
  40. // newCharacter can be undefined if the onMutate hook fails
  41. if (newCharacter) {
  42. // directly cancel queries with a temp id and remove cache entry
  43. queryCache.getEntries({ key: characterByIdQuery(newCharacter.id).key, exact: true })
  44. .map((entry) => {
  45. queryCache.cancel(entry)
  46. queryCache.remove(entry)
  47. })
  48. }
  49. }
  50. },
  51. onError(error, { optimisticUpdates }, { oldCharacterList, newCharacterList, oldOptions }) {
  52. // before applying the rollback, check if the value in the cache is the same
  53. // in case the cache was updated by another mutation or query
  54. if (optimisticUpdates && newCharacterList === queryCache.getQueryData(characterListQuery.key)) {
  55. console.log("[useCreateCharacter] [onError] [rollback]")
  56. queryCache.setQueryData(characterListQuery.key, oldCharacterList)
  57. queryCache.setQueryData(characterOptionsQuery.key, oldOptions)
  58. }
  59. // handle the error
  60. console.error("[useCreateCharacter] [onError]", error)
  61. },
  62. onSuccess(character, { optimisticUpdates }, { oldCharacterList }) {
  63. console.log("[useCreateCharacter] [onSuccess]", character)
  64. if (optimisticUpdates) {
  65. // create a copy of oldCharacterList with newly returned character
  66. const characterList = [...oldCharacterList || [], character]
  67. queryCache.setQueryData(characterListQuery.key, characterList)
  68. }
  69. }
  70. })
  71. return {
  72. ...mutation,
  73. createCharacter: (character) => mutate({ character, optimisticUpdates: true }),
  74. createCharacterFromEvent: (character) => mutate({ character, optimisticUpdates: false })
  75. }
  76. })