我在做一个项目时偶然发现了一个问题,我有一个用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完全运行之前就填写了这个字段,所以它不可能截获这个事件。
我研究了一下,结果迷失在浏览器的不一致和自动填充工作方式的差异中,所以我不得不创建一个简单的变通方法。
我使用useRef 和useEffect 。
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这样的库时应该避免的,但它可以解决这个问题。
如果没有自动填写怎么办?这将简单地等待,直到第一个字符被输入,并将停止循环。