import { useCallback } from 'react' ; import merge from 'lodash/merge' ; import { useSafeSetState } from '../util/hooks' ; import { MutationMode , OnSuccess , OnFailure } from '../types' ; import useDataProvider from './useDataProvider' ; import useDataProviderWithDeclarativeSideEffects from './useDataProviderWithDeclarativeSideEffects' ; import { DeclarativeSideEffect } from './useDeclarativeSideEffects' ; param query param { string } query . type param { string } query . resource param { Object } query . payload param options param { string } options . action param { boolean } options . undoable param { boolean } options . returnPromise param { Function } options . onSuccess param { Function } options . onFailure param { boolean } options . withDeclarativeSideEffectsSupport returns example example example const useMutation = ( query ? , options ? ) : UseMutationValue => { const [ state , setState ] = useSafeSetState ( { data : null , error : null , total : null , loading : false , loaded : false , } ) ; const dataProvider = useDataProvider ( ) ; const dataProviderWithDeclarativeSideEffects = useDataProviderWithDeclarativeSideEffects ( ) ; const mutate = useCallback ( ( callTimeQuery ? , callTimeOptions ? ) : void | Promise < any > => { const finalDataProvider = hasDeclarativeSideEffectsSupport ( options , callTimeOptions ) ? dataProviderWithDeclarativeSideEffects : dataProvider ; const params = mergeDefinitionAndCallTimeParameters ( query , callTimeQuery , options , callTimeOptions ) ; setState ( prevState => ( { ... prevState , loading : true } ) ) ; const returnPromise = params . options . returnPromise ; const promise = finalDataProvider [ params . type ] . apply ( finalDataProvider , typeof params . resource !== 'undefined' ? [ params . resource , params . payload , params . options ] : [ params . payload , params . options ] ) . then ( response => { const { data , total } = response ; setState ( { data , error : null , loaded : true , loading : false , total , } ) ; if ( returnPromise ) { return response ; } } ) . catch ( errorFromResponse => { setState ( { data : null , error : errorFromResponse , loaded : false , loading : false , total : null , } ) ; if ( returnPromise ) { throw errorFromResponse ; } } ) ; if ( returnPromise ) { return promise ; } } , [ JSON . stringify ( { query , options } ) , dataProvider , dataProviderWithDeclarativeSideEffects , setState , ] ) ; return [ mutate , state ] ; } ; export interface Mutation { type : string ; resource ? : string ; payload ? : object ; } export interface MutationOptions { action ? : string ; returnPromise ? : boolean ; onSuccess ? : OnSuccess | DeclarativeSideEffect ; onFailure ? : OnFailure | DeclarativeSideEffect ; withDeclarativeSideEffectsSupport ? : boolean ; deprecated undoable ? : boolean ; mutationMode ? : MutationMode ; } export type UseMutationValue = [ ( query ? : Partial < Mutation > | Event , options ? : Partial < MutationOptions > ) => void | Promise < any > , { data ? : any ; total ? : number ; error ? : any ; loading : boolean ; loaded : boolean ; } ] ; param query { Mutation } param callTimeQuery { Mutation } param options { Object } param callTimeOptions { Object } return { type const mergeDefinitionAndCallTimeParameters = ( query ? , callTimeQuery ? , options ? , callTimeOptions ? ) : { type : string ; resource : string ; payload ? : object ; options : MutationOptions ; } => { if ( ! query && ( ! callTimeQuery || callTimeQuery instanceof Event ) ) { throw new Error ( 'Missing query either at definition or at call time' ) ; } const event = callTimeQuery as Event ; if ( callTimeQuery instanceof Event || ! ! event ?. preventDefault ) return { type : query . type , resource : query . resource , payload : query . payload , options : sanitizeOptions ( options ) , } ; if ( query ) { return { type : callTimeQuery ?. type || query . type , resource : callTimeQuery ?. resource || query . resource , payload : callTimeQuery ? merge ( { } , query . payload , callTimeQuery . payload ) : query . payload , options : callTimeOptions ? merge ( { } , sanitizeOptions ( options ) , sanitizeOptions ( callTimeOptions ) ) : sanitizeOptions ( options ) , } ; } return { type : callTimeQuery . type , resource : callTimeQuery . resource , payload : callTimeQuery . payload , options : options ? merge ( { } , sanitizeOptions ( options ) , sanitizeOptions ( callTimeOptions ) ) : sanitizeOptions ( callTimeOptions ) , } ; } ; const hasDeclarativeSideEffectsSupport = ( options ? , callTimeOptions ? ) => { if ( ! options && ! callTimeOptions ) return false ; if ( callTimeOptions && callTimeOptions . withDeclarativeSideEffectsSupport ) return true ; return options && options . withDeclarativeSideEffectsSupport ; } ; const sanitizeOptions = ( args ? ) => { if ( ! args ) return { onSuccess : undefined } ; const { withDeclarativeSideEffectsSupport , ... options } = args ; return { onSuccess : undefined , ... options } ; } ; export default useMutation ;