Skip to content

Commit eff0c20

Browse files
TylerRickerikras
andauthored
Forward refs to input component (#608)
* Wrap Field with forwardRef * Add a prepare script that builds dist/ so that dist won't be missing if you install the package from from a git repo instead of from npm * Document that the ref is forwarded * Typed forwardRef call Co-authored-by: Erik Rasmussen <[email protected]>
1 parent f750d23 commit eff0c20

File tree

3 files changed

+84
-54
lines changed

3 files changed

+84
-54
lines changed

docs/types/FieldProps.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,10 @@ A function that takes the value from the input and name of the field and convert
189189

190190
**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 `''`.**
191191

192+
## `ref`
193+
194+
The `ref` is forwarded to the component provided by the `component` prop.
195+
192196
## `render`
193197

194198
<!-- prettier-ignore -->

src/Field.js

Lines changed: 64 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -4,62 +4,72 @@ import type { FieldProps as Props, FieldRenderProps } from './types'
44
import renderComponent from './renderComponent'
55
import useField from './useField'
66

7-
const Field = ({
8-
afterSubmit,
9-
allowNull,
10-
beforeSubmit,
11-
children,
12-
component,
13-
data,
14-
defaultValue,
15-
format,
16-
formatOnBlur,
17-
initialValue,
18-
isEqual,
19-
multiple,
20-
name,
21-
parse,
22-
subscription,
23-
type,
24-
validate,
25-
validateFields,
26-
value,
27-
...rest
28-
}: Props) => {
29-
const field: FieldRenderProps = useField(name, {
30-
afterSubmit,
31-
allowNull,
32-
beforeSubmit,
33-
children,
34-
component,
35-
data,
36-
defaultValue,
37-
format,
38-
formatOnBlur,
39-
initialValue,
40-
isEqual,
41-
multiple,
42-
parse,
43-
subscription,
44-
type,
45-
validate,
46-
validateFields,
47-
value
48-
})
7+
const Field = React.forwardRef<any, Props>(
8+
(
9+
{
10+
afterSubmit,
11+
allowNull,
12+
beforeSubmit,
13+
children,
14+
component,
15+
data,
16+
defaultValue,
17+
format,
18+
formatOnBlur,
19+
initialValue,
20+
isEqual,
21+
multiple,
22+
name,
23+
parse,
24+
subscription,
25+
type,
26+
validate,
27+
validateFields,
28+
value,
29+
...rest
30+
}: Props,
31+
ref
32+
) => {
33+
const field: FieldRenderProps = useField(name, {
34+
afterSubmit,
35+
allowNull,
36+
beforeSubmit,
37+
children,
38+
component,
39+
data,
40+
defaultValue,
41+
format,
42+
formatOnBlur,
43+
initialValue,
44+
isEqual,
45+
multiple,
46+
parse,
47+
subscription,
48+
type,
49+
validate,
50+
validateFields,
51+
value
52+
})
4953

50-
if (typeof children === 'function') {
51-
return (children: Function)({ ...field, ...rest })
52-
}
54+
if (typeof children === 'function') {
55+
return (children: Function)({ ...field, ...rest })
56+
}
5357

54-
if (typeof component === 'string') {
55-
// ignore meta, combine input with any other props
56-
return React.createElement(component, { ...field.input, children, ...rest })
58+
if (typeof component === 'string') {
59+
// ignore meta, combine input with any other props
60+
return React.createElement(component, {
61+
...field.input,
62+
children,
63+
ref,
64+
...rest
65+
})
66+
}
67+
return renderComponent(
68+
{ children, component, ref, ...rest },
69+
field,
70+
`Field(${name})`
71+
)
5772
}
58-
return renderComponent(
59-
{ children, component, ...rest },
60-
field,
61-
`Field(${name})`
62-
)
63-
}
73+
)
6474

6575
export default Field

src/Field.test.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,22 @@ describe('Field', () => {
405405
expect(CustomSelect.mock.calls[0][0].input.multiple).toBe(true)
406406
})
407407

408+
it('should pass ref through to the input', () => {
409+
const ref = React.createRef()
410+
render(
411+
<Form onSubmit={onSubmitMock} subscription={{ values: true }}>
412+
{() => (
413+
<form>
414+
<Field name="name" component="input" ref={ref} />
415+
</form>
416+
)}
417+
</Form>
418+
)
419+
420+
expect(ref.current).not.toBe(null)
421+
expect(ref.current instanceof HTMLInputElement).toBe(true)
422+
})
423+
408424
it('should not pass an undefined type through to the input', () => {
409425
const MyInput = jest.fn(({ input }) => <input {...input} />)
410426
render(

0 commit comments

Comments
 (0)