Когда именно устанавливаются состояния React Hook? - PullRequest
0 голосов
/ 26 сентября 2019

Я пытаюсь понять порядок выполнения следующего фрагмента кода, включающего состояния 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?

Ответы [ 2 ]

1 голос
/ 27 сентября 2019

Помните: все ваши переменные состояния являются локальными переменными.Они существуют только в это конкретное время для визуализируемого компонента.Таким образом, при первом рендеринге console.log("filtered arr length", filteredArr.length); ссылается на массив, существующий в этом первом рендере.filteredArr никогда не будет назначен новый массив (это не может быть, это const), и если вы не мутируете массив (чего не следует делать), длина этого массива всегда будет равна 0.

Когда вы вызываете setFilteredArr, это дает команду реагировать на повторную визуализацию компонента.React может выполнять рендеринг синхронно или может подождать, чтобы попытаться выполнить пакетную обработку изменений.Когда происходит второй рендеринг, вы вызываете useState и возвращаете новое значение.Это присваивается локальной переменной с именем FilterArr, но это совершенно другая переменная, чем та, которая была у нас при первом рендере.Оператор console.log в этом первом рендере не будет иметь доступа к переменной во втором рендере.Но у второго рендера есть доступ к нему, поэтому при любом журналировании во второй раз будет показан второй массив.

0 голосов
/ 27 сентября 2019

setState или 'setFilteredLength' является асинхронной операцией.После его вызова потребуется некоторое время для обновления состояния (поскольку оно асинхронное, оно не будет ждать этого обновления. Оно просто выполнит следующую строку), поэтому при выполнении console.log значение не изменилось -> пока что

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...