Repository: final-form/react-final-form (js)

Issue:
Get Field Component via refs
### Are you submitting a **bug report** or a **feature request**?
feature request

### What is the current behavior?
There is no a way to get Field components via refs.

### What is the expected behavior?
Access to the rendered component in a Field `<Field {....} component={MyCustomField} />`.

### What's your environment?
- final-form": "^4.2.0"
- react-final-form": "^3.1.0

### Other information
I am using this library in a React Native App, so the behavior that I would like to implement is this: Focus a field when clicking on "Next" key in the virtual keyboard on iOS. 


Pull request:
Forward refs to input component
Resolves #141 

Still to do:
- [x] Make the same change to Field in `react-final-form-html5-validation` (final-form/react-final-form-html5-validation#18)
- [x] Add a test
- [x] Update docs
- [ ] Get Flow typings to work in Field.js


Patch:
diff --git a/docs/types/FieldProps.md b/docs/types/FieldProps.md
index 82267bd..bdd2d02 100644
--- a/docs/types/FieldProps.md
+++ b/docs/types/FieldProps.md
@@ -189,6 +189,10 @@ A function that takes the value from the input and name of the field and convert
 
 **Note: If would like to override the default behavior of converting `''` to `undefined`, you can pass an [identity function](https://en.wikipedia.org/wiki/Identity_function), `v => v`, to `parse`, thus allowing you to have form values of `''`.**
 
+## `ref`
+
+The `ref` is forwarded to the component provided by the `component` prop.
+
 ## `render`
 
 <!-- prettier-ignore -->
diff --git a/src/Field.js b/src/Field.js
index baab6f0..3564262 100644
--- a/src/Field.js
+++ b/src/Field.js
@@ -4,62 +4,72 @@ import type { FieldProps as Props, FieldRenderProps } from './types'
 import renderComponent from './renderComponent'
 import useField from './useField'
 
-const Field = ({
-  afterSubmit,
-  allowNull,
-  beforeSubmit,
-  children,
-  component,
-  data,
-  defaultValue,
-  format,
-  formatOnBlur,
-  initialValue,
-  isEqual,
-  multiple,
-  name,
-  parse,
-  subscription,
-  type,
-  validate,
-  validateFields,
-  value,
-  ...rest
-}: Props) => {
-  const field: FieldRenderProps = useField(name, {
-    afterSubmit,
-    allowNull,
-    beforeSubmit,
-    children,
-    component,
-    data,
-    defaultValue,
-    format,
-    formatOnBlur,
-    initialValue,
-    isEqual,
-    multiple,
-    parse,
-    subscription,
-    type,
-    validate,
-    validateFields,
-    value
-  })
+const Field = React.forwardRef<any, Props>(
+  (
+    {
+      afterSubmit,
+      allowNull,
+      beforeSubmit,
+      children,
+      component,
+      data,
+      defaultValue,
+      format,
+      formatOnBlur,
+      initialValue,
+      isEqual,
+      multiple,
+      name,
+      parse,
+      subscription,
+      type,
+      validate,
+      validateFields,
+      value,
+      ...rest
+    }: Props,
+    ref
+  ) => {
+    const field: FieldRenderProps = useField(name, {
+      afterSubmit,
+      allowNull,
+      beforeSubmit,
+      children,
+      component,
+      data,
+      defaultValue,
+      format,
+      formatOnBlur,
+      initialValue,
+      isEqual,
+      multiple,
+      parse,
+      subscription,
+      type,
+      validate,
+      validateFields,
+      value
+    })
 
-  if (typeof children === 'function') {
-    return (children: Function)({ ...field, ...rest })
-  }
+    if (typeof children === 'function') {
+      return (children: Function)({ ...field, ...rest })
+    }
 
-  if (typeof component === 'string') {
-    // ignore meta, combine input with any other props
-    return React.createElement(component, { ...field.input, children, ...rest })
+    if (typeof component === 'string') {
+      // ignore meta, combine input with any other props
+      return React.createElement(component, {
+        ...field.input,
+        children,
+        ref,
+        ...rest
+      })
+    }
+    return renderComponent(
+      { children, component, ref, ...rest },
+      field,
+      `Field(${name})`
+    )
   }
-  return renderComponent(
-    { children, component, ...rest },
-    field,
-    `Field(${name})`
-  )
-}
+)
 
 export default Field


Test patch:
diff --git a/src/Field.test.js b/src/Field.test.js
index 888eaf5..1e8c5e4 100644
--- a/src/Field.test.js
+++ b/src/Field.test.js
@@ -405,6 +405,22 @@ describe('Field', () => {
     expect(CustomSelect.mock.calls[0][0].input.multiple).toBe(true)
   })
 
+  it('should pass ref through to the input', () => {
+    const ref = React.createRef()
+    render(
+      <Form onSubmit={onSubmitMock} subscription={{ values: true }}>
+        {() => (
+          <form>
+            <Field name="name" component="input" ref={ref} />
+          </form>
+        )}
+      </Form>
+    )
+
+    expect(ref.current).not.toBe(null)
+    expect(ref.current instanceof HTMLInputElement).toBe(true)
+  })
+
   it('should not pass an undefined type through to the input', () => {
     const MyInput = jest.fn(({ input }) => <input {...input} />)
     render(