Skip to content
This repository has been archived by the owner on Dec 27, 2022. It is now read-only.

Commit

Permalink
feat: introduce onRawSubmit and parseSubmitException (#150)
Browse files Browse the repository at this point in the history
* feat: introduce onRawSubmit and parseSubmitException

* docs: add doc

* chore: update locifle
  • Loading branch information
chambo-e authored Mar 21, 2022
1 parent fbb91b4 commit 9459d6b
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 3 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,8 @@
"final-form": "4.20.6",
"final-form-arrays": "3.0.2",
"final-form-focus": "1.1.2",
"react-final-form": "6.5.8"
"react-final-form": "6.5.8",
"react-final-form-arrays": "3.1.3"
},
"dependenciesMeta": {
"@react-spring/core": {
Expand Down
17 changes: 17 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 28 additions & 0 deletions src/components/Form/__tests__/__snapshots__/index.spec.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,20 @@ exports[`Form renders correctly with node children 1`] = `
</DocumentFragment>
`;

exports[`Form renders correctly with onRawSubmit which should take precedence 1`] = `
<DocumentFragment>
<form
novalidate=""
>
<button
type="submit"
>
Submit
</button>
</form>
</DocumentFragment>
`;

exports[`Form renders correctly with onSubmit that return {} 1`] = `
<DocumentFragment>
<form
Expand Down Expand Up @@ -62,6 +76,20 @@ exports[`Form renders correctly with onSubmit that throw 1`] = `
</DocumentFragment>
`;

exports[`Form renders correctly with parseSubmitException 1`] = `
<DocumentFragment>
<form
novalidate=""
>
<button
type="submit"
>
Submit
</button>
</form>
</DocumentFragment>
`;

exports[`Form renders correctly with validate 1`] = `
<DocumentFragment>
<form
Expand Down
59 changes: 59 additions & 0 deletions src/components/Form/__tests__/index.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,63 @@ describe('Form', () => {
},
)
})

test('renders correctly with parseSubmitException', () => {
const onSubmit = jest.fn(() => Promise.reject(new Error('error')))
const onSubmitSuccess = jest.fn(() => {})
const onSubmitError = jest.fn(() => {})
const parseSubmitException = jest.fn(() => 'parsed error')

return shouldMatchEmotionSnapshot(
<Form
errors={mockErrors}
onSubmitSuccess={onSubmitSuccess}
onSubmit={onSubmit}
onSubmitError={onSubmitError}
parseSubmitException={parseSubmitException}
>
<button type="submit">Submit</button>
</Form>,
{
transform: async ({ getByText }) => {
userEvent.click(getByText('Submit'))
expect(onSubmit).toBeCalledTimes(1)
await waitFor(() => expect(onSubmitError).toBeCalledTimes(1))
await waitFor(() => expect(parseSubmitException).toBeCalledTimes(1))
expect(parseSubmitException).toBeCalledWith(new Error('error'))
expect(onSubmitSuccess).toBeCalledTimes(0)
},
},
)
})

test('renders correctly with onRawSubmit which should take precedence', () => {
const onSubmit = jest.fn(() => Promise.reject(new Error('error')))
const onSubmitSuccess = jest.fn(() => {})
const onRawSubmit = jest.fn(() => {})
const onSubmitError = jest.fn(() => {})
const parseSubmitException = jest.fn(() => 'parsed error')

return shouldMatchEmotionSnapshot(
<Form
errors={mockErrors}
onSubmitSuccess={onSubmitSuccess}
onSubmit={onSubmit}
onSubmitError={onSubmitError}
parseSubmitException={parseSubmitException}
onRawSubmit={onRawSubmit}
>
<button type="submit">Submit</button>
</Form>,
{
transform: async ({ getByText }) => {
userEvent.click(getByText('Submit'))
await waitFor(() => expect(onRawSubmit).toBeCalledTimes(1))
expect(onSubmit).toBeCalledTimes(0)
expect(onSubmitError).toBeCalledTimes(0)
expect(parseSubmitException).toBeCalledTimes(0)
},
},
)
})
})
31 changes: 29 additions & 2 deletions src/components/Form/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,24 @@ export type FormProps<FormValues = unknown> = {
| ((props: FormRenderProps<FormValues, Partial<FormValues>>) => ReactNode)
| ReactNode
errors: FormErrors
/**
* onRawSubmit is the base onSubmit from final-form
*/
onRawSubmit?: ReactFinalFormProps<FormValues, Partial<FormValues>>['onSubmit']
/**
* onSubmit acts as onRawSubmit but will call onSubmitSuccess/Error lifecycles
* and will parse eexception with parseSubmitException if provided
* @deprecated its behavior is inconsistent, favor onRawSubmit
*/
onSubmit?: ReactFinalFormProps<FormValues, Partial<FormValues>>['onSubmit']
onSubmitSuccess?: OnSubmitSucccessFn<FormValues>
onSubmitError?: OnSubmitErrorFn
/**
* parseSubmitException will be invoked on onSubmit throw
* It will take the error and must return a readable string or undefined
* @deprecated its behavior is inconsistent, favor onRawSubmit
*/
parseSubmitException?: (error: unknown) => string | undefined
initialValues?: Partial<FormValues>
validateOnBlur?: ReactFinalFormProps<
FormValues,
Expand All @@ -36,6 +51,7 @@ export type FormProps<FormValues = unknown> = {
}
const Form = <FormValues,>({
children,
onRawSubmit,
onSubmit,
onSubmitError,
onSubmitSuccess,
Expand All @@ -47,18 +63,25 @@ const Form = <FormValues,>({
render,
mutators,
keepDirtyOnReinitialize,
parseSubmitException,
}: FormProps<FormValues>): JSX.Element => (
<ErrorProvider errors={errors}>
<ReactFinalForm
initialValues={initialValues}
validateOnBlur={validateOnBlur}
validate={validate}
decorators={[focusOnErrors as unknown as Decorator<FormValues, Partial<FormValues>>]}
decorators={[
focusOnErrors as unknown as Decorator<FormValues, Partial<FormValues>>,
]}
mutators={{
...arrayMutators,
...mutators,
}}
onSubmit={async (values, form, callback) => {
if (onRawSubmit) {
return onRawSubmit(values, form, callback)
}

try {
const res = await onSubmit?.(values, form, callback)
if (res !== undefined) {
Expand All @@ -71,7 +94,11 @@ const Form = <FormValues,>({
} catch (submitError) {
await onSubmitError?.(submitError)

return { [FORM_ERROR]: submitError }
return {
[FORM_ERROR]: parseSubmitException
? parseSubmitException(submitError)
: submitError,
}
}
}}
render={
Expand Down
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ export { default as SwitchField } from './components/SwitchField'
export { default as TagsField } from './components/TagsField'
export { default as TextBoxField } from './components/TextBoxField'
export type { FormErrors } from './types'
export { FormSpy, useFormState, useForm, useField } from 'react-final-form'
export { FieldArray, useFieldArray } from 'react-final-form-arrays'

0 comments on commit 9459d6b

Please sign in to comment.