Cómo solucioné un problema con el estado del formulario de inicio de sesión de React y el autocompletado del navegador

Me encontré con un problema mientras trabajaba en un proyecto que tenía un formulario creado usando React, y cómo el autocompletado del navegador interactuaba con él.

¿Sabe, cuando el navegador pone su nombre de usuario / contraseña automáticamente porque ya lo escribió en el pasado?

Eso es autocompletar, y esa es la causa de mi problema. En particular, lo repliqué en Chrome y Firefox, pero cualquier navegador podría encontrarse con esto.

La forma era una forma habitual y simple construida con eluseStategancho.

Aquí hay un ejemploemailcampo del formulario:

import { useState } from 'react'

//… const [email, setEmail] = useState(’’)

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

Cuando escribe el correo electrónico allí, elemailel valor se actualiza usandosetEmaily lo tendré disponible en el evento de envío de formulario, para poder enviarlo al servidor.

En algún momento me di cuenta de que el navegador estaba completando automáticamente el correo electrónico y la contraseña, ¡pero React no lo reconoció!

Tal vez porque llena el campo antes de que React se esté ejecutando por completo, por lo que no puede interceptar ese evento.

Investigué un poco y me perdí en una tierra de inconsistencias de navegador y diferencias en cómo funciona el autocompletar, así que tuve que crear una solución simple.

Lo hice usandouseRefyuseEffect:

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

Creo una referencia:

const emailField = useRef(null)

y en el JSX lo adjunto al campo de entrada:

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

Luego agregué un fragmento de código que cada 100 ms busca el valor del campo y llamasetEmail()para actualizarlo:

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

No es ideal, implica manipulación DOM, que es algo que debemos evitar cuando usamos una biblioteca como React, pero soluciona este problema.

¿Qué pasa si no hay autocompletar? Esto simplemente esperará hasta que se escriba el primer carácter y detendrá el ciclo.

Descarga mi gratisReact Handbook


Más tutoriales de react: