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)
Если ваш новое состояние зависит от предыдущего, всегда используйте функцию в качестве аргумента.