Open rjray opened 4 years ago
For reference, this is the warning I get:
Warning: React does not recognize the `innerRef` prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase `innerref` instead. If you accidentally passed it from a parent component, remove it from the DOM element.
in input (created by FormControl)
in FormControl (created by Field)
in Field (at MagazineForm.js:73)
in div (created by Col)
in Col (at MagazineForm.js:72)
in div (created by FormRow)
in FormRow (created by FormGroup)
in FormGroup (at MagazineForm.js:67)
in form (created by Form)
in Form (at MagazineForm.js:66)
in Formik (at MagazineForm.js:54)
in MagazineForm (at MagazineUpdate.js:59)
in div (created by Container)
in Container (at MagazineUpdate.js:69)
in MagazineUpdate (at Magazines.js:13)
in Magazines (created by Context.Consumer)
in Route (at App.js:34)
in Switch (at App.js:20)
in div (created by Container)
in Container (at App.js:19)
in Router (created by BrowserRouter)
in BrowserRouter (at App.js:12)
in App (at src/index.js:10)
The use of innerRef
in the <Field />
component was:
<Field
...
innerRef={input => { saveRef = input }}
....>
etc.
@rjray you're using a custom component which means you'll receive innerRef
as a prop instead of ref
. Not sure the reasoning behind that, but we would pass ref itself when #2208 lands (probably not until TS + forwardRef work with generics, or we can ignore a specific TS error message). Until then, your component should look like:
// and whatever other props you want to separate
const FormControl = ({ innerRef, ...rest }) => (
<input ref={innerRef} {...rest} />
);
@johnrom Hi, im kind of in the same situation im trying to make it so when the 'next' button in keyboard is pressed the next input is focused so i thought i'd need refs for that. Here I created Refs in the constructor, and tried to give it to the input but it gives undefined errors... How would your example look like using this code:
<Field
name="email"
label="email"
component={Input}
onChangeText={formikProps.handleChange('email')}
value={formikProps.values.email}
keyboardType="email-address"
touched={formikProps.touched.email}
errors={formikProps.errors.email}
returnKeyType="next"
onSubmitEditing={() => this.current.passwordInput.focus()}
innerRef={ (input) => { this.emailInput = input }}
onBlur={formikProps.handleBlur('email')}
/>
Well, almost nine months later and I've finally cracked this. Funny-enough, when I sat down to try this again and Googled for "react formik innerref" this issue was the first search result presented. Always fun when the first search-hit is your own original question...
But anyway.
My problem was that I am using a custom component (<Form.Control />
) that I don't have control over; it's part of React Bootstrap. But reading the answer above from @johnrom suddenly clicked. So I did this:
const FocusFormControl = ({ innerRef, ...props }) => (
<Form.Control ref={innerRef} {...props} />
);
I then changed the <Field />
invocation to:
<Field
as={FocusFormControl}
onBlur={handleBlur}
onChange={handleChange}
type="text"
name="name"
innerRef={(el) => (autoFocusRef.current = el)}
placeholder="Name"
autoFocus
data-lpignore="true"
/>
Here, autoFocusRef
was a prop passed in to my form-creation component. No errors, and no spew in the console.
For the sake of helping @MannySAD and anyone else who comes across this, I used this in conjunction with a custom hook that I gleaned from this StackOverflow question (look for the high-score answer). Here is the hook:
import { useRef } from "react";
export const useFocus = () => {
const htmlElRef = useRef(null);
const setFocus = () => {
htmlElRef.current && htmlElRef.current.focus();
};
return [htmlElRef, setFocus];
};
And then:
const [focus, setFocus] = useFocus();
...
<TagForm
submitHandler={submitHandler}
tag={{ name: "", description: "", type: "" }}
autoFocusRef={focus}
/>
Then a call to setFocus()
when I need to re-focus to the main input.
Hi - I'm trying to autofocus on the first input in my form. AFAICT I'm using default Formik elements, not customizing them in any way. This form is in a React Function component.
<Formik
initialValues={{ displayName: '', email: '', password: '' }}
onSubmit=...
>
<Form>
<Field
name="displayName"
type="text"
placeholder="username"
// set focus on this field
/>
....
I've tried a bunch of ways based on the answers (including from the SO link) above to make this work but am utterly confused. In your (@rjray) example, I see that you make a hook, then (I think) you use that hook to set a custom prop you've added to a customized Formik element (?).
I've tried your approach (creating the hook, however since my Form components aren't custom, I've opted to try using the following props on the <Field />
component, based on a number of SO and other types of posts I've seen - ref
, innerRef
, refs
.
None of these seem to work, either crashing altogether or simply not focusing the Field
.
To summarize, I'm using the following default Formik elements in a React Function component:
<Formik>, <Form>, <Field>
I would like to focus the <Field>
element, when the Component first renders.
If there is any way anyone can clarify this, I would really appreciate it.
@samyoungnyc if you can provide a codesandbox repo I can help you with this.
You should be able to simply do the following; remove the Typescript if you don't use it.
const MyForm = () => {
const inputRef = useRef<HTMLInputElement>(null);
useEffect(() => {
inputRef.current?.focus();
}, []);
return <Formik {...formikProps>
<Form>
<Field name="myField" ref={inputRef} />
</Form>
</Formik>
}
Using a plain field does not use innerRef. Formik should, in theory, just pass along the plain ref to a plain input
. InnerRef is used for custom components like component={MyComponent}
or as={MyComponent}
. If you tried to pass a ref
to those, TypeScript would error out.
Hi @johnrom - thanks for responding. Apologies for late reply but I tabled this issue for another time. In any case, I've made a codesandbox and fiddled around some more.
I replicated your code (in plain React/JS).
No errors were thrown however the input element didn't focus (in my copy of your component - non-TS).
If I remove the ?
from inputRef.current?.focus();
- the following error occurs:
Cannot read property 'focus' of null
I did a little more digging - and realized that my component structure was the larger part of the issue. I had 2 components (login + signup) that were children of a parent component (2 tabs to choose + render either form). The first tab was login, and the 2nd was sign up (where I wanted the focus). I realized however that both login+signup components were being rendered within my two-tab structure, so switching to the 2nd tab, did not re-render, and thus the ref
wasn't being focused (this I don't understand fully).
Finally, using ref
wasn't working so I switched the order of my tabs so that the signup form was first, and used innerRef
instead of ref
and it finally worked.
In any case, if you have just one form - the following should work:
import React, { useRef, useEffect } from "react";
import "./styles.css";
import { Formik, Field, Form, ErrorMessage } from "formik";
const MyForm = () => {
const inputRef = useRef(null);
useEffect(() => {
return inputRef.current?.focus();
}, []);
return (
<Formik>
<Form>
<label>name: </label>
<Field name="myField" innerRef={inputRef} />
</Form>
</Formik>
)
}
export default MyForm;
Hope this helps someone in the future, and thanks for the feedback!
I'm glad people are being helpful and providing solutions... but, did they docs get improved? Because that's partially what the OP was all about. Also, improving the docs will help WAY more people than posting solutions in this thread.
Hi - I'm trying to autofocus on the first input in my form. AFAICT I'm using default Formik elements, not customizing them in any way. This form is in a React Function component.
<Formik initialValues={{ displayName: '', email: '', password: '' }} onSubmit=... > <Form> <Field name="displayName" type="text" placeholder="username" // set focus on this field /> ....
I've tried a bunch of ways based on the answers (including from the SO link) above to make this work but am utterly confused. In your (@rjray) example, I see that you make a hook, then (I think) you use that hook to set a custom prop you've added to a customized Formik element (?).
I've tried your approach (creating the hook, however since my Form components aren't custom, I've opted to try using the following props on the
<Field />
component, based on a number of SO and other types of posts I've seen -ref
,innerRef
,refs
.None of these seem to work, either crashing altogether or simply not focusing the
Field
.To summarize, I'm using the following default Formik elements in a React Function component:
<Formik>, <Form>, <Field>
I would like to focus the
<Field>
element, when the Component first renders.If there is any way anyone can clarify this, I would really appreciate it.
use innerRef props inside
📖 Documentation
Currently, the
innerRef
property is documented under<Field />
. However, putting it there results in a warning to the console. Other readings indicate that it should be passed to the<Formik />
element. But there is no indication of how to then use the ref to access actual form DOM elements (such as to set focus on a specific field).