Last active
October 10, 2022 21:06
-
-
Save wuweiweiwu/a4bcfc86133a4684e3c531540ff68446 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// given a commit function from useMutation | |
// return a promisfied version of the commit function that resolves to the mutation data | |
// and rejects with the mutation error | |
export function promisfy<TMutation extends MutationParameters>(commit: (config: UseMutationConfig<TMutation>) => Disposable) { | |
return (config: UseMutationConfig<TMutation>) => { | |
return new Promise<TMutation['response']>((resolve, reject) => { | |
// override the onComplete and onError callbacks to promisfy commit | |
const newConfig: UseMutationConfig<TMutation> = { | |
...config, | |
onCompleted: (data, errors) => { | |
config.onCompleted?.(data, errors); | |
resolve(data); | |
}, | |
onError: (error) => { | |
config.onError?.(error); | |
reject(error); | |
}, | |
}; | |
commit(newConfig); | |
}); | |
}; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export type DeepPartial<T> = { | |
[P in keyof T]?: DeepPartial<T[P]>; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as React from 'react'; | |
import { GraphQLTaggedNode, applyOptimisticMutation } from 'react-relay'; | |
import { UseMutationConfig, useRelayEnvironment, useMutation as useRelayMutation } from 'react-relay/hooks'; | |
import { MutationParameters } from 'relay-runtime'; | |
import merge from 'deepmerge'; | |
import { promisfy } from './promisfy'; | |
import { DeepPartial } from './types'; | |
// similar to useMutation but returns a start function | |
// start immediately applies to optimistic update and returns an object with 2 values | |
// - undo reverts the optimistic update | |
// - commit sends the network request and returns a promise that resolves with the response or rejects with error | |
export function useUndoableMutation<TMutation extends MutationParameters>( | |
mutation: GraphQLTaggedNode | |
): ( | |
config: UseMutationConfig<TMutation> | |
) => { | |
undo: () => void; | |
commit: (configOverride?: DeepPartial<UseMutationConfig<TMutation>>) => Promise<TMutation['response']>; | |
} { | |
const environment = useRelayEnvironment(); | |
const [relayCommit] = useRelayMutation<TMutation>(mutation); | |
const start = React.useCallback( | |
(config: UseMutationConfig<TMutation>) => { | |
// apply optimistic mutation using the same config as to the actual mutation | |
const disposable = applyOptimisticMutation(environment, { ...config, mutation }); | |
return { | |
undo: () => disposable.dispose(), | |
commit: (configOverride?: DeepPartial<UseMutationConfig<TMutation>>) => { | |
disposable.dispose(); | |
const promisfiedCommit = promisfy(relayCommit); | |
return promisfiedCommit(merge(config, configOverride || {})); | |
}, | |
}; | |
}, | |
[environment, mutation, relayCommit] | |
); | |
return start; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment