Содержание
useState() — это хук, который предназначен для работы с состоянием компонента в приложениях на React и работает только в функциональных компонентах.
Для чего нужен useState()
Данный хук используется для:
- управления состоянием, в том числе передачи данных как пропсов другим компонентам
- условного рендеринга — рендер тех или иных данных, в зависимости от того, что хранится в стейте
- для переключения состояния (true/false)
- как счетчик чего-либо
- хранения данных полученных от сервера
Самый простой пример использования:
import React, { useState } from "react";
export default function App() {
const [state, setState] = useState('Hello World');
return (
<div className="App">
<h1>{ state }</h1>
</div>
);
}
Хук useState()
возвращает состояние (state) и функцию для его изменения (setState). Название данной функции и переменной задаете вы сами. C помощью деструктуризации ([state, setState]
) мы сразу получаем значения.
В качестве параметра хук принимает значение по умолчанию. В нашем случае это строка Hello World.
Данный пример очень простой и в такой реализации нам состояние даже не понадобиться, мы могли бы сразу в заголовок прописать данную строку.
Давайте рассмотрим другой пример. У нас есть поле ввода и в зависимости от того, что мы вводим, будет изменяться заголовок:
import React, { useState } from "react";
export default function App() {
const [title, setTitle] = useState('');
const changeTitle = (e) => {
const newTitle = e.target.value;
setTitle(newTitle);
}
return (
<div className="App">
<h1>{ title }</h1>
<input type='text' name='title' value={title} onChange={(e) => changeTitle(e)} />
</div>
);
}
Теперь у нас состояние называется title и функция, которая будет его изменять — setTitle. Добавляем input
с обработчиком изменений changeTitle. В обработчике мы получаем значение из инпута (e.target.value) и с помощью функции для обновления состояния setTitle меняем его на новый.
Сейчас независимо от того, есть у нас title или нет, тег h1
будет отображаться все равно. На этом же примере мы можем рассмотреть условный рендеринг. В примере ниже если title не задан, тогда тег <h1>
не будет отображаться:
return (
<div className="App">
{ title && <h1>{ title }</h1> }
<input type='text' name='title' value={title} onChange={(e) => changeTitle(e)} />
</div>
);
Также возможен другой вариант. Вы можете в зависимости от условия делать разный return
if (title)
return <h1>{ title }</h1>
return (
<input type='text' name='title' value={title} onChange={(e) => changeTitle(e)} />
);
Если title
задан отрисовываем его, если нет отрисовываем инпут для ввода тайтла.
В состоянии компонента вы можете хранить строки, числа, массивы, объект и т.д.
Сохранение данных с сервера с помощью хука useState()
Для хранения данных полученных с сервера нам дополнительно понадобиться хук useEffect()
:
import React, { useEffect, useState } from "react";
export default function App() {
const [posts, setPosts] = useState([]);
useEffect(() => {
fetch("https://jsonplaceholder.typicode.com/posts")
.then((response) => response.json())
.then((json) => setPosts(json));
}, []);
if (!posts.length) return <h4>Loading...</h4>;
return (
<>
<h1>POSTS</h1>
<ul>
{posts.map(post => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</>
);
}
Теперь давайте рассмотрим, что у нас есть. У нас есть api (https://jsonplaceholder.typicode.com/posts), который возвращает нам массив из 100 постов. Все асинхронные действия в функциональных компонентах должны делаться с помощью хука useEffect
, поэтому мы с помощью fecth
получаем посты и дальше сохраняем их в posts с помощью функции setPosts
.
Далее, чтобы сделать список постов, мы проходимся методом map()
по массиву и на каждой итерации отрисовываем элемент li
с уникальным ключом key.
Использование useState() с объектом
Рассмотрим теперь такой пример, где у нас state это объект и нам необходимо будет его обновлять:
import React, { useState } from "react";
export default function App() {
const [user, setUser] = useState({});
const handleFieldChange = (e) => {
const { name: fieldName, value: fieldValue } = e.target;
const updatedUser = {
...user,
[fieldName]: fieldValue
};
setUser(updatedUser);
};
return (
<>
<h1>USER</h1>
<ul>
<li>First Name: {user.firstName || ""}</li>
<li>Last Name: {user.lastName || ""}</li>
<li>Age: {user.age || ""}</li>
</ul>
<hr />
<form>
<label>
Name
<input
type="text"
name="firstName"
onChange={(e) => handleFieldChange(e)}
/>
</label>
<label>
Last Name
<input
type="text"
name="lastName"
onChange={(e) => handleFieldChange(e)}
/>
</label>
<label>
Age
<input
type="number"
name="age"
onChange={(e) => handleFieldChange(e)}
/>
</label>
</form>
</>
);
}
У нас есть user
, по умолчанию это пустой объект, и есть форма ниже для указания необходимых полей пользователя. У всех полей формы есть одинаковый обработчик — handleFieldChange
, с его помощью мы получаем вводимые значения, далее с помощью деструктуризации мы получаем имя и значение поля, создаем новый объект, куда помещаем уже существующие поля у user (строка 10) и добавляем новые поля. Затем обновляем state.
Добавить комментарий