Skip to content

Commit

Permalink
feat(form): remove final-form legacy props and hook (#3780)
Browse files Browse the repository at this point in the history
* feat(form): remove final-form legacy props and hook
  • Loading branch information
johnrazeur authored Jul 3, 2024
1 parent 7dee114 commit 64af9b3
Show file tree
Hide file tree
Showing 95 changed files with 795 additions and 859 deletions.
69 changes: 69 additions & 0 deletions .changeset/khaki-ants-grow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---
"@ultraviolet/form": major
---

## Accept control prop

Field can accept a `control` prop. When this prop is provided, the `name` prop must be present in the form and the `onChange` callback is typed.

## Remove defaultValues

You must use the `useForm` hook to provide initial values:

```tsx
// Old
<Form defaultValues={{ foo: 'bar' }}>
// ...
</Form>

// New
const methods = useForm({ defaultValues: { foo: 'bar' }})

<Form methods={methods}>
// ...
</Form>
```

## Remove function as child component

Function as child component must be remove:

```tsx
// Old
<Form>
{({ isSubmitting }) => (
<Button disabled={isSubmitting}>Submit</Button>
)}
</Form>

// New
const methods = useForm()

const { isSubmitting } = methods.formState

<Form methods={methods}>
<Button disabled={isSubmitting}>Submit</Button>
</Form>
```

## onRawSubmit renamed to onSubmit

The `onRawSubmit` is renamed to `onSubmit`.

The return of the function is now a string if an error occurred.

```tsx
// Old
<Form onRawSubmit={(values) => {
return { [FORM_ERROR]: 'ERROR' }
}}>
// ...
</Form>

// New
<Form onSubmit={(values) => {
return 'ERROR'
}}>
// ...
</Form>
```
10 changes: 2 additions & 8 deletions examples/next-login/src/pages/home/login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,7 @@ const LogIn = () => {

return (
<StyledLoginContainer>
<Form<FormValues>
methods={methods}
errors={mockErrors}
onRawSubmit={handleSubmit}
>
<Form methods={methods} errors={mockErrors} onSubmit={handleSubmit}>
<Stack gap={1} alignItems="center">
<Icon name="id" size="1.7em" />
<Text as="h1" variant="heading">
Expand All @@ -69,9 +65,7 @@ const LogIn = () => {
name="email"
required
placeholder="example@email.com"
rules={{
pattern: { value: EMAIL_REGEX, message: 'Invalid format' },
}}
regex={[EMAIL_REGEX]}
/>
<StyledInput
label="Password"
Expand Down
6 changes: 2 additions & 4 deletions examples/next-login/src/pages/home/signup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ const SignUp = () => {
<Form<FormValues>
methods={methods}
errors={mockErrors}
onRawSubmit={handleSubmit}
onSubmit={handleSubmit}
>
<Stack gap={1} alignItems="center">
<Icon name="profile" size="1.7em" />
Expand Down Expand Up @@ -130,9 +130,7 @@ const SignUp = () => {
name="email"
required
placeholder="example@email.com"
rules={{
pattern: { value: EMAIL_REGEX, message: 'Invalid format' },
}}
regex={[EMAIL_REGEX]}
className="inputs"
/>
<StyledInput
Expand Down
67 changes: 67 additions & 0 deletions packages/form/src/__stories__/migrations/MigrationFormV3.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { Meta } from '@storybook/blocks'

<Meta title="Migrations/Formv2 to Formv3" />

# Migrate Formv2 to Formv3

## Remove defaultValues

You must use the `useForm` hook to provide initial values:

```tsx
// Old
<Form defaultValues={{ foo: 'bar' }}>
// ...
</Form>

// New
const methods = useForm({ defaultValues: { foo: 'bar' }})

<Form methods={methods}>
// ...
</Form>
```

## Remove function as child component

Function as child component must be remove:

```tsx
// Old
<Form>
{({ isSubmitting }) => (
<Button disabled={isSubmitting}>Submit</Button>
)}
</Form>

// New
const methods = useForm()

const { isSubmitting } = methods.formState

<Form methods={methods}>
<Button disabled={isSubmitting}>Submit</Button>
</Form>
```

## onRawSubmit renamed to onSubmit

The `onRawSubmit` is renamed to `onSubmit`.

The return of the function is now a string if an error occurred.

```tsx
// Old
<Form onRawSubmit={(values) => {
return { [FORM_ERROR]: 'ERROR' }
}}>
// ...
</Form>

// New
<Form onSubmit={(values) => {
return 'ERROR'
}}>
// ...
</Form>
```
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import type { StoryFn } from '@storybook/react'
import { CheckboxField } from '..'
import { useForm } from '../../..'
import type { FormErrors } from '../../../types'
import { Form } from '../../Form'

export const BooleanChecked: StoryFn<{ errors: FormErrors }> = ({ errors }) => (
<Form onRawSubmit={() => {}} errors={errors} initialValues={{ foo: true }}>
<CheckboxField name="foo">Default Checked Boolean Item</CheckboxField>
</Form>
)
export const BooleanChecked: StoryFn<{ errors: FormErrors }> = ({ errors }) => {
const methods = useForm({ defaultValues: { foo: true } })

return (
<Form onSubmit={() => {}} errors={errors} methods={methods}>
<CheckboxField name="foo">Default Checked Boolean Item</CheckboxField>
</Form>
)
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import type { StoryFn } from '@storybook/react'
import { CheckboxField } from '..'
import { useForm } from '../../..'
import type { FormErrors } from '../../../types'
import { Form } from '../../Form'

export const Checked: StoryFn<{ errors: FormErrors }> = ({ errors }) => (
<Form onRawSubmit={() => {}} errors={errors} initialValues={{ foo: true }}>
<CheckboxField name="foo">Checked Item</CheckboxField>
<CheckboxField name="bar">Not Checked Item</CheckboxField>
</Form>
)
export const Checked: StoryFn<{ errors: FormErrors }> = ({ errors }) => {
const methods = useForm({ defaultValues: { foo: true } })

return (
<Form onSubmit={() => {}} errors={errors} methods={methods}>
<CheckboxField name="foo">Checked Item</CheckboxField>
<CheckboxField name="bar">Not Checked Item</CheckboxField>
</Form>
)
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { Meta } from '@storybook/react'
import { Snippet, Stack, Text } from '@ultraviolet/ui'
import { useForm } from 'react-hook-form'
import { CheckboxField, Form } from '../..'
import { useForm } from '../../..'
import { mockErrors } from '../../../mocks'

export default {
Expand All @@ -24,7 +24,7 @@ export default {
} = methods.formState

return (
<Form onRawSubmit={() => {}} errors={mockErrors} methods={methods}>
<Form onSubmit={() => {}} errors={mockErrors} methods={methods}>
<Stack gap={2}>
<ChildStory />
<Stack gap={1}>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { act, screen } from '@testing-library/react'
import { act, renderHook, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { mockFormErrors, renderWithForm, renderWithTheme } from '@utils/test'
import { useForm } from 'react-hook-form'
import { describe, expect, test, vi } from 'vitest'
import { CheckboxField } from '../..'
import { Form } from '../../Form'
Expand All @@ -24,7 +25,7 @@ describe('CheckboxField', () => {

test('should render correctly checked without value', () => {
const { asFragment } = renderWithForm(<CheckboxField name="checked" />, {
initialValues: {
defaultValues: {
checked: true,
},
})
Expand All @@ -36,7 +37,7 @@ describe('CheckboxField', () => {

test('should render correctly not checked without value', () => {
const { asFragment } = renderWithForm(<CheckboxField name="checked" />, {
initialValues: {},
defaultValues: {},
})

const input = screen.getByRole('checkbox', { hidden: true })
Expand Down Expand Up @@ -71,8 +72,13 @@ describe('CheckboxField', () => {
})

test('should render correctly with errors', async () => {
const { result } = renderHook(() => useForm({ mode: 'onChange' }))
const { asFragment } = renderWithTheme(
<Form onRawSubmit={() => {}} errors={mockFormErrors}>
<Form
onSubmit={() => {}}
errors={mockFormErrors}
methods={result.current}
>
<CheckboxField name="test" required>
Checkbox field error
</CheckboxField>
Expand Down
16 changes: 9 additions & 7 deletions packages/form/src/components/CheckboxField/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import type { BaseFieldProps } from '../../types'

type CheckboxFieldProps<
TFieldValues extends FieldValues,
TName extends FieldPath<TFieldValues>,
> = Omit<BaseFieldProps<TFieldValues, TName>, 'value'> &
TFieldName extends FieldPath<TFieldValues>,
> = Omit<BaseFieldProps<TFieldValues, TFieldName>, 'value'> &
Partial<
Pick<
ComponentProps<typeof Checkbox>,
Expand All @@ -29,9 +29,10 @@ type CheckboxFieldProps<

export const CheckboxField = <
TFieldValues extends FieldValues,
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
TFieldName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
>({
id,
control,
name,
label,
size,
Expand All @@ -43,23 +44,24 @@ export const CheckboxField = <
onChange,
onBlur,
onFocus,
rules,
helper,
tooltip,
'data-testid': dataTestId,
shouldUnregister = false,
}: CheckboxFieldProps<TFieldValues, TName>) => {
validate,
}: CheckboxFieldProps<TFieldValues, TFieldName>) => {
const { getError } = useErrors()
const {
field,
fieldState: { error },
} = useController<TFieldValues>({
} = useController<TFieldValues, TFieldName>({
name,
disabled,
shouldUnregister,
control,
rules: {
required,
...rules,
validate,
},
})

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { StoryFn } from '@storybook/react'
import { Stack } from '@ultraviolet/ui'
import { useFormContext } from 'react-hook-form'
import { CheckboxGroupField } from '..'
import { useFormContext } from '../../..'

export const DirectionStory: StoryFn<typeof CheckboxGroupField> = args => {
const { watch } = useFormContext()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type { Meta } from '@storybook/react'
import { Snippet, Stack, Text } from '@ultraviolet/ui'
import { useForm } from 'react-hook-form'
import { CheckboxGroupField } from '..'
import { Form } from '../..'
import { useForm } from '../../..'
import { mockErrors } from '../../../mocks'

export default {
Expand Down Expand Up @@ -30,7 +30,7 @@ export default {

return (
<Form
onRawSubmit={data => {
onSubmit={data => {
console.log('data', data)
}}
errors={mockErrors}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ describe('CheckboxField', () => {
</CheckboxGroupField.Checkbox>
</CheckboxGroupField>,
{
initialValues: {
defaultValues: {
Checkbox: [],
},
},
Expand Down Expand Up @@ -51,7 +51,7 @@ describe('CheckboxField', () => {
</CheckboxGroupField.Checkbox>
</CheckboxGroupField>,
{
initialValues: {
defaultValues: {
test: [],
},
},
Expand Down
Loading

0 comments on commit 64af9b3

Please sign in to comment.