如何修复React登录表单状态和浏览器自动填充的问题

497 阅读2分钟

我在做一个项目时偶然发现了一个问题,我有一个用React构建的表单,以及浏览器自动填充与它的互动。

你知道,当浏览器自动输入你的用户名/密码时,因为你在过去已经输入了它?

这就是自动填充,这就是我的问题的原因。我特别在Chrome和Firefox上复制了这个问题,但任何浏览器都可能遇到这个问题。

这个表单是一个用useState 钩子构建的普通而简单的表单。

这里有一个表单的例子email 字段。

import { useState } from 'react'

//...

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

当你在那里输入电子邮件时,email 的值会使用setEmail 进行更新,我会在表单提交事件中提供它,所以我可以把它发送到服务器上。

在某种程度上,我意识到浏览器在自动填写电子邮件和密码,但React却没有识别它!这是为什么?

也许是因为它在React完全运行之前就填写了这个字段,所以它不可能截获这个事件。

我研究了一下,结果迷失在浏览器的不一致和自动填充工作方式的差异中,所以我不得不创建一个简单的变通方法。

我使用useRefuseEffect

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

我创建了一个ref:

const emailField = useRef(null)

并在JSX中把它附加到输入字段。

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

然后我添加了一段代码,每隔100ms查找该字段的值,并调用setEmail() 来更新它。

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

这并不理想,它涉及到DOM操作,这是我们在使用React这样的库时应该避免的,但它可以解决这个问题。

如果没有自动填写怎么办?这将简单地等待,直到第一个字符被输入,并将停止循环。