Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v3 #2846

Closed
wants to merge 79 commits into from
Closed

v3 #2846

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
b4b1dc0
Add parse, format, formatOnBlur to getFieldProps()
jaredpalmer Jan 28, 2020
5bb4e7c
Add TS types to FieldConfig
jaredpalmer Jan 28, 2020
303ec51
Add parse-format example
jaredpalmer Jan 28, 2020
9be5333
Fix examples
jaredpalmer Feb 6, 2020
d89ed12
Smarter react native event handling
jaredpalmer Feb 6, 2020
a28f1e8
Merge branch 'master' into feat/parse-format
jaredpalmer Feb 6, 2020
ca194f7
Parse Format PR Review Changes (#2280)
johnrom Mar 9, 2020
d750a8f
Migate context to use-context-selector
jaredpalmer Sep 17, 2020
10c9cd0
Merge branch 'master' into feat/parse-format
jaredpalmer Sep 24, 2020
89e5367
Merge branch 'master' into use-context-selector
jaredpalmer Sep 24, 2020
5689ad9
Merge branch 'master' into use-context-selector
jaredpalmer Sep 24, 2020
f01855b
Merge branch 'master' into feat/parse-format
jaredpalmer Sep 24, 2020
e2fe672
Enter prerelease mode
jaredpalmer Oct 27, 2020
91fd5e0
Merge branch 'next' into feat/parse-format
jaredpalmer Oct 27, 2020
5efd691
Add changeset
jaredpalmer Oct 27, 2020
18f82f8
Format string
jaredpalmer Oct 27, 2020
acaf99a
Add parse, format, formatOnBlur to getFieldProps()
jaredpalmer Oct 27, 2020
751322b
Merge branch 'master' into next
jaredpalmer Oct 27, 2020
3d46ee5
Version Packages (next)
github-actions[bot] Oct 27, 2020
30c75f3
Merge pull request #2847 from formium/changeset-release/next
jaredpalmer Oct 27, 2020
ff681d3
Fix format by string pattern example
jaredpalmer Oct 27, 2020
d121546
Fix parse and format in Field component
jaredpalmer Oct 27, 2020
1c2175a
Add changeset
jaredpalmer Oct 27, 2020
76fe988
Merge pull request #2848 from formium/fix/parse
jaredpalmer Oct 27, 2020
4967376
Merge branch 'master' into next
jaredpalmer Oct 27, 2020
86ed17f
Version Packages (next)
github-actions[bot] Oct 27, 2020
96d5dc9
Merge pull request #2849 from formium/changeset-release/next
jaredpalmer Oct 27, 2020
71a9652
Fix format by string example
jaredpalmer Oct 27, 2020
6cf0e93
Add an unlink script to package.json
jaredpalmer Oct 28, 2020
95f65c9
Merge branch 'master' into next
jaredpalmer Nov 7, 2020
235df97
Version Packages (next)
github-actions[bot] Nov 7, 2020
3d8666f
Merge pull request #2877 from formium/changeset-release/next
jaredpalmer Nov 7, 2020
ed83eb1
Merge branch 'master' into next
jaredpalmer Nov 8, 2020
80a73a0
Merge branch 'next' into use-context-selector
jaredpalmer Nov 8, 2020
9e1dd62
Add formik codemod package
jaredpalmer Nov 9, 2020
08babf1
Implement field optimizations with StrictField
jaredpalmer Nov 9, 2020
ee14b4c
Fix ts in codemod
jaredpalmer Nov 9, 2020
7abae43
Use tsdx to test codemod
jaredpalmer Nov 9, 2020
961f009
Fix e2e test
jaredpalmer Nov 9, 2020
dce5e8d
Remove console.lgo
jaredpalmer Nov 9, 2020
9502997
Merge pull request #2749 from formium/use-context-selector
jaredpalmer Nov 10, 2020
e56e830
Implement new error message
jaredpalmer Nov 11, 2020
b059d83
Fix StrictField
jaredpalmer Nov 11, 2020
f4aa35c
Implement Form
jaredpalmer Nov 11, 2020
2219193
Add perf to app
jaredpalmer Nov 11, 2020
6383b86
Add changeset
jaredpalmer Nov 11, 2020
6354f5d
Merge pull request #2893 from formium/form-and-errormsg
jaredpalmer Nov 11, 2020
f37e580
Version Packages (next)
github-actions[bot] Nov 11, 2020
036af69
Merge pull request #2894 from formium/changeset-release/next
jaredpalmer Nov 11, 2020
3a3f52b
Refactor Field and useField
jaredpalmer Nov 12, 2020
8fe165a
Add error message and reimplement fast field
jaredpalmer Nov 13, 2020
4216947
Fix broken import
jaredpalmer Nov 13, 2020
1650120
Fix imports
jaredpalmer Nov 13, 2020
0ad41eb
Add changeset
jaredpalmer Nov 13, 2020
129000e
Make new hooks more useful
jaredpalmer Nov 13, 2020
d33493d
Start migration guide
jaredpalmer Nov 13, 2020
24529bd
Fix cypress tests
jaredpalmer Nov 13, 2020
fdca920
Fix / hack types
jaredpalmer Nov 14, 2020
fc8be9a
Add spacing to error message
jaredpalmer Nov 14, 2020
c8f8cb3
Merge pull request #2903 from formium/rename
jaredpalmer Nov 14, 2020
1fc2fab
Version Packages (next)
github-actions[bot] Nov 14, 2020
f828d75
Merge pull request #2904 from formium/changeset-release/next
jaredpalmer Nov 14, 2020
50433fa
Implement field.onBlur in useField
jaredpalmer Nov 16, 2020
9719fe7
Version Packages (next)
github-actions[bot] Nov 16, 2020
76fa3c7
Merge pull request #2910 from formium/changeset-release/next
jaredpalmer Nov 16, 2020
4e515a4
Fix useFieldTouched selector
jaredpalmer Nov 16, 2020
c001d6e
Version Packages (next)
github-actions[bot] Nov 16, 2020
3c51c71
Merge pull request #2911 from formium/changeset-release/next
jaredpalmer Nov 16, 2020
a7ecaed
Merge branch 'master' into next
jaredpalmer Nov 18, 2020
90fd693
Add missing hooks
jaredpalmer Nov 19, 2020
e4eb06a
Merge pull request #2921 from formium/more-hooks
jaredpalmer Nov 19, 2020
679800b
Version Packages (next)
github-actions[bot] Nov 19, 2020
d339bfb
Merge pull request #2922 from formium/changeset-release/next
jaredpalmer Nov 19, 2020
ce10b83
Update migration guide
jaredpalmer Nov 19, 2020
577688e
add useSetFieldValue and useSetFieldTouched hooks
seropaski Dec 1, 2020
0e57c8d
add changeset
seropaski Dec 2, 2020
56690f3
Merge pull request #2939 from seropaski/next
jaredpalmer Dec 2, 2020
aa0b9fe
Version Packages (next)
github-actions[bot] Dec 2, 2020
1c36c1c
Merge pull request #2941 from formium/changeset-release/next
jaredpalmer Dec 2, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/afraid-buses-kiss.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'formik': patch
---

Add `useSetFieldValue` and `useSetFieldTouched` hooks
15 changes: 15 additions & 0 deletions .changeset/gentle-boxes-turn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
'formik': patch
---

Added optimized Form, ErrorMessage, and the following additional optimized field-level hooks
and components that only rerender when their respective slices have changed:

- `unstable_useFieldValue`
- `unstable_useFieldTouched`
- `unstable_useFieldError`
- `unstable_useStrictField`
- `unstable_StrictField`

In addition, there is a very very unstable `unstable_useFormikContextSelector` that we'll be using
to prototype other APIss in product that is also included. This will definitely **not** be released, so you have been warned.
5 changes: 5 additions & 0 deletions .changeset/honest-radios-poke.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'formik': patch
---

Fix useFieldTouched selector
5 changes: 5 additions & 0 deletions .changeset/lazy-olives-agree.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'formik': patch
---

Add hooks `useSetValue`, `useSetErrors`, `useSetTouched`, `useSetStatus`, `useSubmitForm`, `useResetForm`, `useIsSubmitting`, `useIsValid`, `useIsDirty`, `useValidateForm`, `useValidateField`
5 changes: 5 additions & 0 deletions .changeset/little-olives-enjoy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'formik': patch
---

Ensure that parse and format aren't passed through in Field components
19 changes: 19 additions & 0 deletions .changeset/pre.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"mode": "pre",
"tag": "next",
"initialVersions": {
"formik": "2.2.1",
"formik-native": "2.1.9",
"@formik/codemod": "3.0.0-next.2"
},
"changesets": [
"afraid-buses-kiss",
"gentle-boxes-turn",
"honest-radios-poke",
"lazy-olives-agree",
"little-olives-enjoy",
"quiet-beans-attack",
"two-fans-film",
"wicked-goats-burn"
]
}
8 changes: 8 additions & 0 deletions .changeset/quiet-beans-attack.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'formik': major
---

Added `parse`, `format`, and `formatOnBlur` to `getFieldProps` options, `<Field>`, and `useField`. Going forward, there is no reason aside from backwards compatibility to continue using either `formikProps.handleChange` or `formikProps.handleBlur`. These are both inferior to the `onChange` and `onBlur` functions returned by `getFieldProps()` which the ability to utilize `parse`, `format`, and `formatOnBlur`.

**Breaking Change**
Instead of just passing back `formikProps.handleChange` and `formikProps.handleBlur`, the `onChange` and `onBlur` handlers returned by `getFieldProps()` (and thus `useField`/`<Field>`) are now scoped to the field already and now accept either a React Synthetic event or a value. In the past, you could need to curry the handler with the string name of field to get this functionality. This likely doesn't impact many users, but it is technically breaking nonetheless.
19 changes: 19 additions & 0 deletions .changeset/two-fans-film.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
'formik': patch
---

Renames `unstable_StrictField` to `FastField` and thus deprecates `<FastField shouldUpdate>` prop. If you need this functionality, use `useFormikContext()` and `useField()` in a custom component wrapped in `React.memo()` instead. In addition, and this is breaking, `FastField` is no longer passed `form` object in any render prop.

If you still need to access the `form` object in render use `FormikConsumer` like so:

```diff
- import { FastField } from 'formik'
+ import { FastField, FormikConsumer } from 'formik'

<FastField name="firstName">
- {({ field, meta, form }) => ( /* ... */ )}
+ {({ field, meta }) => (
+ <FormikConsumer>{form => /* ... */}</FormikConsumer>
+ )}
</FastField>
```
5 changes: 5 additions & 0 deletions .changeset/wicked-goats-burn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'formik': patch
---

Implement useField field.onBlur to avoid rerendering entire form on blur events
47 changes: 47 additions & 0 deletions MIGRATING-v3.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Formik 3 Migration Guide

## Breaking changes

- `FastField` no longer accepts `shouldUpdate` prop. Given the new implementation of `FastField`, this functionality is likely no longer needed anyways.
- `FastField` is no longer passed a `form` object (which contained `formikProps` in any render prop. If you still need to access the `form` object in the render prop use regular `Field` (which updates on every render).
- Instead of just passing back `formikProps.handleChange` and `formikProps.handleBlur`, the `onChange` and `onBlur` handlers returned by `getFieldProps()` and `useField`/`<Field>`/`<FastField>`) are now scoped to the field already and now accept either a React Synthetic event or a value. In the past, you could curry the handler with the string name of field to get this functionality. This likely doesn't impact many users, but it is technically breaking nonetheless.

## Improvements

- Selective rendering!
- `<Form>`, `<ErrorMessage>`, and `<FastField>` have been re-implemented to optimize rendering (i.e. minimally re-render)
- `useField()` no longer updates on every key stroke, but only when that field is updated. This is a massive performance boost.
- Added `parse`, `format`, and `formatOnBlur` to `getFieldProps` options, `<Field>`, and `useField`. Going forward, there is no reason aside from backwards compatibility to continue using either `formikProps.handleChange` or `formikProps.handleBlur`. These are both inferior to the `onChange` and `onBlur` functions returned by `getFieldProps()`, `<Field>`/`<FastField>`'s `field` object, or `useField` which have the ability to utilize `parse`, `format`, and `formatOnBlur`.
- **New Hooks!**
- `useFieldInitialValue`
- `useFieldInitialTouched`
- `useFieldInitialError`
- `useInitialValues`
- `useInitialErrors`
- `useInitialTouched`
- `useInitialStatus`
- `useFieldTouched`
- `useFieldValue`
- `useFieldError`
- `useValues`
- `useSetValue`
- `useSetErrors`
- `useErrors`
- `useTouched`
- `useSetTouched`
- `useStatus`
- `useSetStatus`
- `useSubmitForm`
- `useResetForm`
- `useIsSubmitting`
- `useIsValid`
- `useIsDirty`
- `useValidateForm`
- `useValidateField`

## Performance Suggestions

- Prefer `<FastField>` to `<Field>`
- Prefer a custom component with `useField()` over `<Field>`
- The new helpers in `field.onChange` and `field.onBlur` returned from `useField()` can now handle either events or raw values. There is thus no need to call `useFormikContext` just to access `setFieldValue` and `setFieldBlur` anymore if you're updating the same field.
- Move away from using `useFormikContext` and instead use one or more of the above hooks (ideally only the `useFieldXXX` ones if you can). `useFormikContext`, `useValues`, `useTouched` and `useErrors` hooks will rerender any components that use them when they change. Unless you're making a debugger, in most cases, your field or component doesn't need all of Formik state and so instead, use the new `useFieldXXX` hooks which will only rerender if that particular slice of Formik state updates.
6 changes: 6 additions & 0 deletions app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,16 @@
"start": "next start"
},
"dependencies": {
"format-string-by-pattern": "^1.2.1",
"formik": "^2.1.5",
"next": "9.5.3",
"react": "16.13.1",
"react-dom": "16.13.1",
"yup": "^0.29.3"
},
"devDependencies": {
"@types/node": "^14.14.6",
"@types/react": "^16.9.56",
"@types/react-dom": "^16.9.9"
}
}
46 changes: 46 additions & 0 deletions app/pages/format.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import React from 'react';
import { Formik, Field, Form } from 'formik';
import formatString from 'format-string-by-pattern';

const masks = [
{ name: 'phone-1', parse: '999-999-9999' },
{ name: 'phone-2', parse: '(999) 999-9999' },
{ name: 'phone-3', parse: '+49 (AAAA) BBBBBB' },
];

const sleep = (ms: number) => new Promise(r => setTimeout(r, ms));

export default function Example() {
return (
<div>
<Formik
initialValues={masks.reduce((prev, curr) => {
prev[curr.name] = '';
return prev;
}, {} as any)}
onSubmit={async values => {
await sleep(300);
alert(JSON.stringify(values, null, 2));
}}
>
<Form>
{masks.map(mask => (
<div key={mask.name}>
<label>
{mask.name}
<Field
name={mask.name}
type="text"
parse={formatString(mask.parse)}
placeholder={mask.parse}
/>
</label>
</div>
))}

<button type="submit">Submit</button>
</Form>
</Formik>
</div>
);
}
5 changes: 5 additions & 0 deletions app/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ function Home() {
<a>Async Submission</a>
</Link>
</li>
<li>
<Link href="/format">
<a>Parse + Format</a>
</Link>
</li>
</ul>
<style jsx>{`
main {
Expand Down
123 changes: 123 additions & 0 deletions app/pages/perf.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import React from 'react';
import { Formik, FastField as Field, Form, ErrorMessage } from 'formik';
import * as Yup from 'yup';

let renderCount = 0;

const Basic = () => (
<div>
<h1>Sign Up</h1>
<Formik
initialValues={{
firstName: '',
lastName: '',
email: '',
favorite: '',
checked: [],
picked: '',
lastName2: '',
lastName3: '',
lastName4: '',
lastName5: '',
lastName6: '',
lastName7: '',
lastName8: '',
lastName9: '',
lastName10: '',
lastName11: '',
lastName12: '',
lastName13: '',
lastName14: '',
lastName15: '',
lastName16: '',
lastName17: '',
lastName18: '',
lastName19: '',
lastName20: '',
}}
validationSchema={Yup.object().shape({
email: Yup.string().email('Invalid email address').required('Required'),
firstName: Yup.string().required('Required'),
lastName: Yup.string()
.min(2, 'Must be longer than 2 characters')
.max(20, 'Nice try, nobody has a last name that long')
.required('Required'),
})}
onSubmit={async values => {
await new Promise(r => setTimeout(r, 500));
alert(JSON.stringify(values, null, 2));
}}
>
<Form>
<Field name="firstName" placeholder="Jane" />
<ErrorMessage name="firstName" component="p" />

<Field name="lastName" placeholder="Doe" />
<Field name="lastName2" placeholder="Doe" />
<Field name="lastName3" placeholder="Doe" />
<Field name="lastName4" placeholder="Doe" />
<Field name="lastName5" placeholder="Doe" />
<Field name="lastName6" placeholder="Doe" />
<Field name="lastName7" placeholder="Doe" />
<Field name="lastName8" placeholder="Doe" />
<Field name="lastName9" placeholder="Doe" />
<Field name="lastName10" placeholder="Doe" />
<Field name="lastName11" placeholder="Doe" />
<Field name="lastName12" placeholder="Doe" />
<Field name="lastName13" placeholder="Doe" />
<Field name="lastName14" placeholder="Doe" />
<Field name="lastName15" placeholder="Doe" />
<Field name="lastName16" placeholder="Doe" />
<Field name="lastName17" placeholder="Doe" />
<Field name="lastName18" placeholder="Doe" />
<Field name="lastName19" placeholder="Doe" />
<Field name="lastName20" placeholder="Doe" />
<ErrorMessage name="lastName" component="p" />

<Field
id="email"
name="email"
placeholder="jane@acme.com"
type="email"
/>
<ErrorMessage name="email" component="p" />

<label>
<Field type="checkbox" name="toggle" />
<span style={{ marginLeft: 3 }}>Toggle</span>
</label>

<div id="checkbox-group">Checkbox Group </div>
<div role="group" aria-labelledby="checkbox-group">
<label>
<Field type="checkbox" name="checked" value="One" />
One
</label>
<label>
<Field type="checkbox" name="checked" value="Two" />
Two
</label>
<label>
<Field type="checkbox" name="checked" value="Three" />
Three
</label>
</div>
<div id="my-radio-group">Picked</div>
<div role="group" aria-labelledby="my-radio-group">
<label>
<Field type="radio" name="picked" value="One" />
One
</label>
<label>
<Field type="radio" name="picked" value="Two" />
Two
</label>
</div>
<button type="submit">Submit</button>
<div id="renderCounter">{renderCount++}</div>
</Form>
</Formik>
</div>
);

export default Basic;
Loading