Repository: final-form/react-final-form
Pull request #546 (2019-06-22 08:46:12)

Cleanup onBlur dependencies

codecov[bot]: # [Codecov](https://codecov.io/gh/final-form/react-final-form/pull/546?src=pr&el=h1) Report
> Merging [#546](https://codecov.io/gh/final-form/react-final-form/pull/546?src=pr&el=desc) into [master](https://codecov.io/gh/final-form/react-final-form/commit/8674fc7002e986b7fcc3136abf0ece921312cda8?src=pr&el=desc) will **not change** coverage.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/final-form/react-final-form/pull/546/graphs/tree.svg?width=650&token=s8VUe6IxMZ&height=150&src=pr)](https://codecov.io/gh/final-form/react-final-form/pull/546?src=pr&el=tree)

```diff
@@          Coverage Diff          @@
##           master   #546   +/-   ##
=====================================
  Coverage     100%   100%           
=====================================
  Files          16     16           
  Lines         228    228           
  Branches       56     56           
=====================================
  Hits          228    228
```


| [Impacted Files](https://codecov.io/gh/final-form/react-final-form/pull/546?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [src/useField.js](https://codecov.io/gh/final-form/react-final-form/pull/546/diff?src=pr&el=tree#diff-c3JjL3VzZUZpZWxkLmpz) | `100% <100%> (ø)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/final-form/react-final-form/pull/546?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/final-form/react-final-form/pull/546?src=pr&el=footer). Last update [8674fc7...8badbc0](https://codecov.io/gh/final-form/react-final-form/pull/546?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/README.md b/README.md
index 0fbd914..d182d90 100644
--- a/README.md
+++ b/README.md
@@ -138,6 +138,7 @@ const MyForm = () => (
   - [Calculated Fields](#calculated-fields)
   - [Field Warnings](#field-warnings)
   - [Reusable Field Groups](#reusable-field-groups)
+  - [Prefixed Fields](#prefixed-fields)
   - [External Submit](#external-submit)
   - [Wizard Form](#wizard-form)
   - [Parse and Format (and Normalize)](#parse-and-format-and-normalize)
@@ -197,6 +198,7 @@ const MyForm = () => (
     - [`meta.active?: boolean`](#metaactive-boolean)
     - [`meta.data?: Object`](#metadata-object)
     - [`meta.dirty?: boolean`](#metadirty-boolean)
+    - [`meta.dirtySinceLastSubmit?: boolean`](#metadirtysincelastsubmit-boolean)
     - [`meta.error?: any`](#metaerror-any)
     - [`meta.initial?: any`](#metainitial-any)
     - [`meta.invalid?: boolean`](#metainvalid-boolean)
@@ -208,6 +210,7 @@ const MyForm = () => (
     - [`meta.submitting?: boolean`](#metasubmitting-boolean)
     - [`meta.touched?: boolean`](#metatouched-boolean)
     - [`meta.valid?: boolean`](#metavalid-boolean)
+    - [`meta.validating?: boolean`](#metavalidating-boolean)
     - [`meta.visited?: boolean`](#metavisited-boolean)
   - [`FormProps`](#formprops)
     - [`children?: ((props: FormRenderProps) => React.Node) | React.Node`](#children-props-formrenderprops--reactnode--reactnode)
@@ -225,7 +228,7 @@ const MyForm = () => (
     - [`validateOnBlur?: boolean`](#validateonblur-boolean)
   - [`FormRenderProps`](#formrenderprops)
     - [`form: FormApi`](#form-formapi)
-    - [`handleSubmit: (?SyntheticEvent<HTMLFormElement>) => void`](#handlesubmit-syntheticeventhtmlformelement--void)
+    - [`handleSubmit: (?SyntheticEvent<HTMLFormElement>) => ?Promise<?Object>`](#handlesubmit-syntheticeventhtmlformelement--promiseobject)
   - [`FormSpyProps`](#formspyprops)
     - [`children?: ((props: FormSpyRenderProps) => React.Node) | React.Node`](#children-props-formspyrenderprops--reactnode--reactnode)
     - [`component?: React.ComponentType<FormSpyRenderProps>`](#component-reactcomponenttypeformspyrenderprops)
@@ -367,6 +370,14 @@ error (thus it does _not_ prevent form submission).
 
 Demonstrates how fields can be grouped into reusable components.
 
+### [Prefixed Fields](https://codesandbox.io/s/react-final-form-prefixed-fields-seiy8)
+
+Demonstrates how the React context API can be used to provide a "prefix wrapper"
+around fields to add structure to your form date. It's similar to how Redux Form's
+[`FormSection`](https://redux-form.com/8.2.2/docs/api/formsection.md/) component works.
+Between this and the [Reusable Field Groups](#reusable-field-groups) example, your
+use case, if migrating from `FormSection` should be handled.
+
 ### [External Submit](https://codesandbox.io/s/1y7noyrlmq)
 
 Demonstrates how you can use `document.getElementById()` or a closure to trigger
@@ -661,6 +672,10 @@ The current value of the field.
 
 [See the 🏁 Final Form docs on `dirty`](https://github.com/final-form/final-form#dirty-boolean).
 
+#### `meta.dirtySinceLastSubmit?: boolean`
+
+[See the 🏁 Final Form docs on `dirty`](https://github.com/final-form/final-form#dirtySinceLastSubmit-boolean).
+
 #### `meta.error?: any`
 
 [See the 🏁 Final Form docs on `error`](https://github.com/final-form/final-form#error-any).
diff --git a/src/useField.js b/src/useField.js
index 5ff5e33..4bcaa7b 100644
--- a/src/useField.js
+++ b/src/useField.js
@@ -126,16 +126,12 @@ function useField<FormValues: FormValuesShape>(
            * before calling `onBlur()`, but before the field has had a chance to receive
            * the value update from Final Form.
            */
-          const fieldState = form.getFieldState(state.name)
-          // this ternary is primarily to appease the Flow gods
-          // istanbul ignore next
-          state.change(
-            format(fieldState ? fieldState.value : state.value, state.name)
-          )
+          const fieldState: any = form.getFieldState(state.name)
+          state.change(format(fieldState.value, state.name))
         }
       },
       // eslint-disable-next-line react-hooks/exhaustive-deps
-      [state.name, state.value, format, formatOnBlur]
+      [state.name, format, formatOnBlur]
     ),
     onChange: React.useCallback(
       (event: SyntheticInputEvent<*> | any) => {
@@ -208,7 +204,7 @@ function useField<FormValues: FormValuesShape>(
   if (value === null && !allowNull) {
     value = ''
   }
-  const input: FieldInputProps = { name, value, type, ...handlers }
+  const input: FieldInputProps = { name, value, ...handlers }
   if (type === 'checkbox') {
     if (_value === undefined) {
       input.checked = !!value
@@ -225,6 +221,9 @@ function useField<FormValues: FormValuesShape>(
   if (multiple) {
     input.multiple = multiple
   }
+  if (type !== undefined) {
+    input.type = type
+  }
 
   const renderProps: FieldRenderProps = { input, meta } // assign to force Flow check
   return renderProps


Test patch:
diff --git a/src/Field.test.js b/src/Field.test.js
index 2a25291..adecdf5 100644
--- a/src/Field.test.js
+++ b/src/Field.test.js
@@ -395,6 +395,23 @@ describe('Field', () => {
     expect(CustomSelect.mock.calls[0][0].input.multiple).toBe(true)
   })
 
+  it('should not pass an undefined type through to the input', () => {
+    const MyInput = jest.fn(({ input }) => <input {...input} />)
+    render(
+      <Form onSubmit={onSubmitMock} subscription={{ values: true }}>
+        {() => (
+          <form>
+            <Field name="name" component={MyInput} multiple />
+          </form>
+        )}
+      </Form>
+    )
+
+    expect(MyInput).toHaveBeenCalled()
+    expect(MyInput).toHaveBeenCalledTimes(1)
+    expect(MyInput.mock.calls[0][0].input).not.toHaveProperty('type')
+  })
+
   it('should optionally allow null values', () => {
     const spy = jest.fn()
     const { getByTestId } = render(