formik icon indicating copy to clipboard operation
formik copied to clipboard

Formik values not updated properly when browser autofills/autocomplete

Open pabloimrik17 opened this issue 3 years ago • 14 comments

Bug report

Current Behavior

Formik do not update properly values property when browser autofills user/password fields.

As you can see on this gif the input has visible values, but not internally (check the console log info on the first two renders)

Once i touch the screen (in this case opening the dev tools with F12) the onChanges are triggered and then formik updates. Also notice how the clear button is visible at end the of each input once i touch the screen.

formik 1

formik 2

image

Im using Ant Desing inputs, but the issue happens too on vanilla HTML inputs

Expected behavior

Formik should have the values updated with the browser autocomplete values

Reproducible example

Im not sure how to make the reproducible example

Your environment

Software Version(s)
Formik 2.2.6
React 16.13.1
TypeScript 4.2.3
Browser Chrome 90.0.4430.93
npm/Yarn 12.18.2
Operating System Windows 10

pabloimrik17 avatar Apr 28 '21 16:04 pabloimrik17

Any update?

pabloimrik17 avatar May 13 '21 14:05 pabloimrik17

This is an upstream issue and a duplicate. There is an issue on React's repository regarding autofill not updating controlled inputs.

I'm on mobile, but if you search these issues for autofill you should see the source issue which links to the React issue.

johnrom avatar May 13 '21 14:05 johnrom

https://github.com/formium/formik/issues/721

johnrom avatar May 13 '21 14:05 johnrom

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 60 days

github-actions[bot] avatar Jun 13 '21 00:06 github-actions[bot]

Facing same issue. There is any solution for this problem? Thanks guys!

lironezra avatar Jun 27 '21 09:06 lironezra

Further reading the upstream issue https://github.com/facebook/react/issues/1159 and https://bugs.chromium.org/p/chromium/issues/detail?id=1166619, it seems that Chrome is giving Javascript access to input values after user interactions.

If Chrome is preventing script spies for security reasons, I don't think they're gonna simulate the onChange event any time soon. This essentially breaks the whole controlled components design in React.

As a workaround, Formik should be possible to perform a last-minute update by reading the submit event before firing onSubmit.

What do you think?

vicary avatar Jul 26 '21 15:07 vicary

I posted a possible fix here -- if that problem is that autofill is occuring before React initializes. If the problem occurs on future "fill" commands using the autofill after the page has already been loaded, it's probably an unsolvable issue (or at least would require sad workarounds like manually reading uncontrolled inputs in a controlled form library).

https://github.com/formium/formik/issues/1047#issuecomment-875708286

Formik is unfortunately a controlled-input library so we wouldn't likely change to use uncontrolled inputs any time soon.

johnrom avatar Jul 26 '21 15:07 johnrom

Screen Shot 2021-11-13 at 01 05 27 I just found the solution, maybe isn't best practice, but this save my time since I also got confused why autofill Mozilla didn't work when I try to login on my app

rfirmansyh avatar Nov 12 '21 16:11 rfirmansyh

I'm with that issue and having to workaround this, it's unfortunate.

DaviGadelhaLeitao avatar Jul 14 '22 22:07 DaviGadelhaLeitao

If you don't want to use useFormik and are using <Formik> you can use my slightly modified workaround that uses the same principle as @rfirmansyh 's:


...

<Formik ...>
  {(props) => (
    <AutofillSync props={props} />
    ...
  )}
</Formik>

...


const AutofillSync = ({ props }: { props: FormikProps<FormData> }) => {
  useEffect(() => {
    if (
      (document.querySelector('input[name="email"]') as HTMLInputElement)?.value ||
      (document.querySelector('input[name="password"]') as HTMLInputElement)?.value
    ) {
      if (!props.values.email || !props.values.password) {
        props.setValues({
          email: (document.querySelector('input[name="email"]') as HTMLInputElement)?.value || "",
          password: (document.querySelector('input[name="password"]') as HTMLInputElement)?.value || "",
        });
      }
    }
  });
  return null;
}

mertcanekiz avatar Jul 25 '22 23:07 mertcanekiz

@mertcanekiz I agree, but I had to add empty dependency to the useEffect:

 useEffect(() => {
    if (
      (document.querySelector('input[name="email"]') as HTMLInputElement)?.value ||
      (document.querySelector('input[name="password"]') as HTMLInputElement)?.value
    ) {
      if (!props.values.email || !props.values.password) {
        props.setValues({
          email: (document.querySelector('input[name="email"]') as HTMLInputElement)?.value || '',
          password: (document.querySelector('input[name="password"]') as HTMLInputElement)?.value || '',
        });
      }
    }
  }, []);

Else, I got in an infinite loop

JonathanCallewaert avatar Sep 21 '22 05:09 JonathanCallewaert

Any updates on this one?

Many users use password managers these days, and having this issue opened forces developers to find alternatives, react-hook-form or something.

exsesx avatar Oct 26 '22 13:10 exsesx

try: https://www.npmjs.com/package/detect-autofill

add eventListener to Field component and set flag "isAutocompleted" to form state

Anastasia-kot avatar Nov 30 '23 16:11 Anastasia-kot

Looks like all these methods with autofill prop are simple ignored by Google Chrome since 2022. I suggest a different method: using readOnly={true} until focus event

Keep in mind that on mobile safari keyboard will not shown if input field change readonly state after focus event, so you need to process onTouchStart too. Heres the link to the source code of usePreventAutofill hook

import { usePreventAutofill } from 'react-declarative';

...

const preventAutofill = usePreventAutofill();

...

return (
  <InputBase

      ...

      {...preventAutofill}
  />   
);
 

tripolskypetr avatar Dec 30 '23 14:12 tripolskypetr