Хук useState
useState – это hook, который позволяет создавать локальный стейт в функциональных компонентах. Точнее это не совсем такой локальный стейт, как у классовых компонент. Так как там он действительно локальный, ведь хранится внутри функции в виде объекта, а здесь же данны хранятся где-то «в стороне» – в мире Реакта. Просто они сохраняются при перезагрузки функций особым образом в этой памяти.
Применение
1. Импортируем из реакт, как и другие хуки:
import React, { useState, useEffect } from 'react';
2. useState всегда возвращает массив с двумя элементами. Вот пример, где мы присваиваем этот массив переменной, а потом достаем первый и второй элемент (так не пишут, это пример!):
let stateWithSetState = useState(true); //отдает массив с двумя элементами let editMode = stateWithSetState[0]; //первый элемент – это само значение let setEditMode = stateWithSetState[1]; //второй элемент – это функция для изменения
3. Как видно из комментариев в примере, первый элемент массива – это само значение (изначально у нас это «true»), а второй – это функция для изменения первого элемента.
4. Когда применяется перерисовка (вызывается функция из второго элемента массива), то компонента перерисовывается.
На практике пишут вот тактим образом:
let [editMode, setEditMode] = useState(false); //деструктивное присваивание для более короткой записи
5. Концепция применения нескольких объектов в хуках отличается от той, что в классовых компонентах. Здесь нужно дробить стейт на несколько элементов, если объектов встейте больше одного. То есть просто каждый раз прописывать то, что в примере выше. Например, нам в компоненте нужен еще один объект дополнительный в локальном стейте:
let [editMode, setEditMode] = useState(false); let [status, setStatus] = useState(props.status); //при работе с хуками приходится для каждого свойства стейта так делать
Пример фрагмента с проекта с применением useState
import React, { useState } from 'react'; import s from './ProfileInfo.module.css'; const ProfileStatusWithHooks = (props) => { let [editMode, setEditMode] = useState(false); let [status, setStatus] = useState(props.status); const activateEditMode = () => { setEditMode(true); //изменяем свойство стейта, чтобы появился инпут для изменения статуса пользователя } const deactivateEditMode = () => { setEditMode(false); //изменяем свойство стейта, чтобы инпут исчез props.updateStatus(status); } const onStatusChange = (e) =>{ setStatus(e.currentTarget.value); } return ( <div> { !editMode && <div> <span onDoubleClick={activateEditMode}>{props.status || "------"}</span> //при двойном клике запускаем изменение стейта </div> } { editMode && <div> <input onChange={onStatusChange} autoFocus={true} onBlur={ deactivateEditMode } //при клике мимо фокуса запускаем изменение стейта value={status} /> </div> } </div> ) } export default ProfileStatusWithHooks;
Этот пример еще сырой, так как в нем теперь нужно применить другой хук – useEffect, чтобы данные из пропсов действительно попадали сразу внутрь инпута при двойном клике по статусу, а не через раз (компонента не всегда успевает загрузиться до получения данных из сервера, которые приходят через пропсы).