useCreateCharacter.js 3.4 KB

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