Created
April 24, 2020 22:00
-
-
Save steida/b48c6c77169e8a84d0bf94368e7086b3 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
import { either } from 'fp-ts'; | |
import { constVoid } from 'fp-ts/lib/function'; | |
import { pipe } from 'fp-ts/lib/pipeable'; | |
import * as t from 'io-ts'; | |
import { useCallback } from 'react'; | |
import { Api } from '../types'; | |
import { useApi } from './useApi'; | |
import { Form, useForm } from './useForm'; | |
export const useMutation = < | |
Name extends keyof Api, | |
Endpoint extends typeof Api['props'][Name] | |
>( | |
name: Name, | |
// t.Output type, because that's what useForm uses. Check useForm.ts to see why. | |
initialState: t.OutputOf<Endpoint['props']['input']>, | |
{ | |
beforeSubmit, | |
handleError, | |
handleSuccess, | |
}: { | |
beforeSubmit?: () => void | boolean; | |
handleError?: ( | |
error: t.TypeOf<Endpoint['props']['error']>, | |
form: Form<Endpoint['props']['input']['props']>, | |
) => void; | |
handleSuccess?: ( | |
payload: t.TypeOf<Endpoint['props']['payload']>, | |
form: Form<Endpoint['props']['input']['props']>, | |
) => void; | |
}, | |
): Form<Endpoint['props']['input']['props']> => { | |
const api = useApi(); | |
const endpoint = Api.props[name]; | |
const handleSubmit = useCallback( | |
(form: Form<Endpoint['props']['input']['props']>) => | |
pipe( | |
form.validated, | |
either.fold(constVoid, (data) => { | |
if (form.isDisabled) return; | |
form.disable(); | |
// any, because we would have to help TypeScript compiler, yolo | |
api<any, any>(name, data)().then((output) => { | |
form.enable(); | |
pipe( | |
output, | |
either.fold( | |
(error) => { | |
if (endpoint.props.inputError.is(error)) | |
// any, because we would have to help TypeScript compiler, yolo | |
form.setAsyncErrors(error.errors as any); | |
if (handleError) handleError(error, form); | |
}, | |
(payload) => { | |
form.reset(); | |
if (handleSuccess) handleSuccess(payload, form); | |
}, | |
), | |
); | |
}); | |
}), | |
), | |
[api, endpoint.props.inputError, handleError, handleSuccess, name], | |
); | |
// any, because we would have to help TypeScript compiler, yolo | |
const form = useForm<any>(endpoint.props.input, initialState, { | |
beforeSubmit, | |
handleSubmit, | |
}); | |
return form; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment