我正在尝试理解以下涉及React Hook状态的代码的执行顺序:
const App = () => {
const [ searchedCountry, setSearchedCountry ] = useState('');
const [ filteredArr, setFilteredArr ] = useState([]);
const [ filteredLength, setFilteredLength ] = useState(0);
//...
const filterCountries = (event) => {
event.preventDefault();
setFilteredArr(countries.filter(country => country.name.includes(searchedCountry)));
setFilteredLength(filteredArr.length);
console.log("filtered arr length", filtered.length);
}
//...
}
当触发filterCountries
时,setFilteredArr
将状态filteredArr
设置为由查询过滤的数组。但是,何时准确设置filteredArr
?
filteredArr.length
返回0
,这意味着即使调用filteredArr
,也尚未设置setFilteredArr
。
[起初,我认为通过执行setFilteredArr
,组件会重新渲染,导致执行跳过setFilteredArr
之后的方法调用。那可以解释为什么filteredArr.length
是0
。但是,仍会调用console.log
,这意味着在重新渲染组件之后,实际上将恢复执行顺序。
发生了什么事?何时准确设置filteredArr
?
要记住的是:您所有的状态变量都是局部变量。它们仅在渲染组件的特定时间存在。因此,在第一个渲染上,console.log("filtered arr length", filteredArr.length);
引用该第一个渲染上存在的数组。 filteredArr
将永远不会被分配一个新数组(它不能,它是一个const),并且除非您对该数组进行了突变(您不应该这样做),否则该数组的长度将始终为0。
当您调用setFilteredArr时,这指示做出反应以重新呈现组件。 React可能会同步进行渲染,或者可能会等待尝试批量添加更改。当第二次渲染发生时,您调用useState并获取新值。这个变量被分配给一个名为filteredArr的局部变量,但这与我们在第一个渲染器上拥有的变量完全不同。该第一个渲染中的console.log语句将无法访问第二个渲染中的变量。但是第二个渲染器可以访问它,因此您第二次执行的任何日志记录都将显示第二个数组。
setState或'setFilteredLength'是异步操作。调用它之后,将需要一些时间来更新状态(因为它是异步的,所以它不会等待该更新。它只会执行下一行),因此在执行console.log时,值没有改变- >尚未