因此,我有一个受控输入组件,并且有一个接受另一个状态变量的 div。这两个状态在单个回调函数中更新。为什么输入中的值和下面div中的文本不同步?
import React, { useState, useRef } from "react";
const Input = () => {
const [search, setSearch] = useState('jk');
const [text, setText] = useState('');
const onChange = (e) => {
setSearch(e.target.value)
setText(search)
}
return (
<>
<input type='text' value={search} onChange={onChange} />
<div>{text}</div>
</>
)
};
export default Input
我知道闭包和过时状态,但是 React 18 的自动批处理不是应该解决这个问题吗?
React 状态更新是不可变的。当您
setSearch(e.target.value)
时,您不会改变组件闭包中的search
变量。直到后续渲染之后,search
变量才会反映您的新值。否则,我们都只会使用常规变量并根据需要改变它们,但是 React 将无法知道它应该重新渲染。
为了更明确地说明这一点:
const [search, setSearch] = useState('jk');
const [text, setText] = useState('');
const onChange = (e) => {
// the `search` variable above will not reflect this new value until the next render
setSearch(e.target.value)
// false (unless they typed "jk" again)
search === e.target.value
// you are still using the old search value from the last render when search was defined as "jk"
setText(search)
}
有两种方法可以解决这个问题。一种是简单地将它们设置为相同的值:
const newSearch = e.target.value
setSearch(newSearch)
setText(newSearch)
^ 我个人更喜欢这个示例中的那个,因为它很简单并且应该只导致一次重新渲染,但另一种模式是使用
useEffect
,因为显示的文本是从搜索值派生的,或者换句话说,你想要更新文本作为搜索值更改的副作用。
const onChange = (e) => {
setSearch(e.target.value)
}
// whenever search changes, update the text
useEffect(() => {
setText(search)
}, [search])