如何获取输入值
我试图在单击按钮时获取输入值,如下所示:
这是我用来存储值的变量:
let textInput = React.createRef();
这是我执行的方式:
<input ref={textInput} type="tel" placeholder="Número de teléfono"></input>
然后,我有一个按钮:
<button onClick={fetchRequest} className="btn btn-default">Comprobar teléfono</button>
它调用这个:
const fetchRequest = useCallback(() => {
database.collection('UsuariosDev').where('Telefono', '==',
textInput.current.value).get()
.then(response => {
const fetchedUsers = [];
response.forEach(document => {
const fetchedUser = {
id: document.id,
...document.data()
};
fetchedUsers.push(fetchedUser);
console.log(fetchedUser)
});
setUsers(fetchedUsers);
if (fetchedUsers.length !== 0) {
setTitle('✔️')
} else {
setTitle('❌')
}
})
}, [])
基本上每次我单击按钮时,我都会进行一次 Firestore 查询。第一次它工作正常,但第二次单击按钮时出现错误,提示 textInput 为空:
TypeError: null is not an object (evaluating 'textInput.current.value')
有什么想法吗?
这里的问题是
useCallback
创建了一个记忆回调。而且由于您提供了一个空的依赖项数组
[]
,因此将始终返回相同的函数。
对于您而言,这是有问题的,因为通过使用
createRef
,每次组件重新渲染时,您都会创建一个新的 ref。
因此,当组件重新渲染时(大概是当您使用
setUsers()
或
setTitle()
更新状态时),您的
fetchRequest
回调并不知道新的 ref。
这里的解决方案可以是:
-
将
textInput
设置为useCallback
的依赖项,以便它知道新创建的 ref
const fetchRequest = useCallback(() => {
...
}, [textInput])
或
-
使用
useRef
而不是
createRef
,这样 ref 就始终相同,即使在重新渲染之后也是如此。
这似乎是由于对输入 DOM 元素的引用在渲染之间丢失而导致的,而记忆化的
useCallback
没有帮助。
当输入的内容发生变化时,您应该使用
onBlur
或
onChange
来更新状态变量,而不是使用
ref={textInput
。
查看有关表单元素的 React 文档
。
这使得分离更加清晰,并确保数据可通过回调函数访问,而不是尝试访问 DOM 节点并提取其当前值。
您可能也不想使用
useCallback
,只需将其作为一个简单的函数即可。
以这种方式使用记忆化进行早期优化是一种坏习惯,因为增加的复杂性可能会增加错误(例如您看到的错误),而且如果设置不正确,还可能返回过时或不正确的信息。
如果您不介意数据变得陈旧,并且存在真正的性能问题,那么您可以使用它,但请记住在最后将电话号码状态变量包含在依赖项数组中。 有关正确用法的文档,请参阅此处 。
您可能想要使用 useRef() Hook,特别是因为它保证在渲染之间保留,而不是 createRef() - 我经常这样做。
同样,作为一种良好的设计实践,我 认为 您想将电话输入和按钮点击分离 - 我会利用 useState() 钩子来更新该输入的电话号码 onChange(),并在获取中引用状态值 - 类似于(警告:未经测试的代码)
const [ telephone, setTelephone] = useState("");
const UpdateUsers = () => {
database.collection('UsuariosDev')
.where('Telefono', '==', telephone)
.get()
.then(response => {
const fetchedUsers = [];
response.forEach(document => {
const fetchedUser = {
...document.data(),
id: document.id
};
fetchedUsers.push(fetchedUser);
console.log(fetchedUser)
});
setUsers(fetchedUsers);
if (fetchedUsers.length !== 0) {
setTitle('✔️')
} else {
setTitle('❌')
}
})
};
<input
onchange={e => setTelephone(e.target.val())}
type="tel"
placeholder="Número de teléfono"
/>
<button
onClick={UpdateUsers}
className="btn btn-default">
Comprobar teléfono
</button>