useState: изменение состояния

Допустим, теперь мы хотим добавить немного интерактивности, и при клике по картинке будем разворачивать покемона. Для каждого покемона у нас есть изображения «вид спереди» и «вид сзади». Эту информацию мы будем хранить в компоненте и называть состоянием — state.

Для чтения и изменения этого состояния нам нужно две переменных соотвественно — переменная с текщим значением и функция для изменения этого значения. Их и возвращет хук useState. Несколько значений из функции удобно возвращать в виде массива, так и поступили авторы реакта.

import { useState } from 'React';

const arr = useState();
const isFront = arr[0];
const setIsFront = arr[1];

Конечно, мы можем использовать деструктуризацию массива.

const [isFront, setIsFront] = useState();

Начальное значение передается первым аргументом в useState.

const [isFront, setIsFront] = useState(true);

Будем инициализировать переменную imgSrc одним из двух значений в зависимости от значения стейта.

const imgSrc = isFront
  ? 'long link 1'
  : 'long link 2';

Как поменять состояние компонента? Нужно вызвать функцию setIsFront с новым значением. Для этого повесим обработчик события handleClick на картинку

function handleClick() {
  setIsFront(false);
}
•••

<img onClick={handleClick} />

О событиях в реакте стоит поговорить в отдельном видео. Сейчас я лишь скажу, что использовать onClick на html-элементах нормально, поскольку это не настоящий html, а jsx, а onClick, написанный кэмел кейсом не является инлайновым лисенером. На деле реакт отлавливает все события на document и использует паттерн делегирования.

После вызова функции setIsFront реакт осуществит ререндер компонента с новым сотоянием.

В данном примере новое состояние зависит от предыдущего, поэтому могли бы сделать так:

setIsFront(!isFront)

К сожалению, такая конструкция работает нестабильно. К моменту исполнения функции setIsFront в переменной isFront, находящейся в замыкании, может оказаться не то значение, которое мы ожидаем. Это тема для отдельного видео.

Безопаснее передать в setIsFront функцию. Эта функция принимает предыдущее состояние и возвращает новое. Она является чистой, поскольку зависит только от своих аргументов.

setIsFront(prevState => !prevState)

Если ваш новое состояние зависит от предыдущего, всегда используйте функцию в качестве аргумента.