I encountered a problem while working on a project that involved a React form and how browser autofill interacts with it.

Browser autofill automatically populates username/password fields when you have previously entered the information. This was causing an issue for me. Specifically, I observed this problem on Chrome and Firefox, but it could potentially occur on any browser.

The form was a basic form built with the useState hook. Here’s an example of the email field:

import { useState } from 'react';

// ...

const [email, setEmail] = useState('');

// ...

<input
 id='email'
 type='email' 
 name='email'
 value={email}
 onChange={(event) => setEmail(event.target.value)} 
/>

When the user enters their email, the email value is updated using setEmail and is available on form submission to be sent to the server.

At some point, I realized that the browser was autofilling the email and password, but React wasn’t recognizing it. It seemed that the browser was filling the field before React had fully initialized, so React couldn’t intercept that event.

I conducted some research and found myself lost in a sea of browser inconsistencies and differences in how autofill works. As a result, I needed to come up with a workaround.

I resolved the issue by using the useRef and useEffect hooks:

import { useState, useEffect, useRef } from 'react';

I created a ref:

const emailField = useRef(null);

Then, I attached the ref to the email input field in JSX:

<input
 ref={emailField}
 id='email'
 type='email' 
 name='email'
 value={email}
 onChange={(event) => setEmail(event.target.value)} 
/>

Next, I added code that checks the value of the field every 100ms and calls setEmail() to update it:

useEffect(() => {
 let interval = setInterval(() => {
 if (emailField.current) {
 setEmail(emailField.current.value);
 // do the same for all autofilled fields
 clearInterval(interval);
 }
 }, 100);
});

While this workaround involves DOM manipulation, which is generally not recommended when using a library like React, it does solve the issue at hand.

If there is no autofill, the code will simply wait until the first character is typed, and then the loop will be stopped.