Здравствуйте, друзья, сегодня я расскажу о хуке useState
в React. Зачем он нам нужен? Потому что useState
отслеживает состояние в функциональном компоненте. Всякий раз, когда данные изменяются, мы используем хук useState
.
Выше я говорил о функциональном компоненте. Поэтому сначала я докажу, что хук useState
является функцией. Скопируйте и вставьте приведенный ниже код:
import { useState } from "react";
const ErrorExample = () => {
console.log(useState);
};
Пояснение к приведенному выше коду:
После этого откройте консоль в вашем браузере (щелкните правой кнопкой мыши на странице и нажмите на inspect), вы увидите следующее:
Итак, useState
— это функция, что она возвращает?
Вызовите функцию в console.log, сделайте это console.log(useState());
.
Как вы видите, useState
возвращает массив. Первый элемент — это значение, а второй — функция. Мы будем управлять значением с помощью функции внутри этого массива.
Первый элемент массива не определен, причина в том, что у него еще нет значения по умолчанию. Мы можем присвоить первому элементу любое значение (массив, объект, число, строка, булево… да что угодно).
Я щелкнул по нему, чтобы показать, что представляет собой f.
Итак, как же мы придадим этому значение? Хотя это не единственный способ, я присваиваю значения следующим образом
Итак, приступим, я объясню приведенный ниже код построчно:
import { useState } from "react";
const ErrorExample = () => {
const [title, setTitle] = useState("this title is gonna be updated");
const changeTitle = () => {
title === "this title is gonna be updated"
? setTitle("useState works!")
: setTitle("this title is gonna be updated");
};
return (
<div>
<h2>useState error example</h2>
<h4>{title}</h4>
<button onClick={changeTitle}>Change title</button>
</div>
);
};
export default ErrorExample;
Во-первых, import { useState } from "react";
import useState from React. Присвойте некоторое значение ‘title’ с помощью useState, а ‘setTitle’ — это функция, с помощью которой мы изменим ‘title’ позже const [title, setTitle] = useState("this title is gonna be updated");
В этом случае начальное значение ‘title’ будет "this title is gonna be updated"
(строка).
const changeTitle = () => {
title === "this title is gonna be updated"
? setTitle("useState works!")
: setTitle("this title is gonna be updated");
};
Код выше начинается с троичного оператора. По сути, это то же самое, что и здесь:
if (title === "this title is gonna be updated") {
setTitle("useState works!")
} else {
setTitle("this title is gonna be updated")
}
То есть, если title равен "этот заголовок будет обновлен"
, измените его значение с помощью функции setTitle
на "useState работает!"
(setTitle(«useState работает!»)). Else (если значение title не равно «this title is going to be updated»), то измените его значение обратно на "this title is going to be updated"
(setTitle(«this title is going to be updated»)).
Последний фрагмент нашего кода:
return (
<div>
<h2>useState error example</h2>
<h4>{title}</h4>
<button onClick={changeTitle}>Change title</button>
</div>
);
<h4>{title}</h4>
‘h4’ тег получает свое значение из const [title, setTitle] = useState("this title is gonna be updated");
. Наконец, элемент button запускает функцию changeTitle
при нажатии на него (onClick={changeTitle}
).
Работа с массивами в useState Hook
Теперь мы немного знаем о useState
, давайте рассмотрим некоторые типы данных, которые могут быть немного запутанными. Так, я рассмотрю массивы и объекты.
Сначала я поделюсь всем кодом:
import { useState } from "react";
// data
const data = [
{id: 0, name: 'Micheal'},
{id: 1, name: 'Ahmet'},
{id: 2, name: 'Daniel'},
]
const ContactList = () => {
const [contacts, setContacts] = useState(data);
const removeContacts = () => {
setContacts([]);
};
const removeContact = (id) => {
const filteredContacts = contacts.filter((contact) => contact.id !== id);
setContacts(filteredContacts);
};
return (
<div>
{contacts.map(({ id, name }) => {
return (
<div style={{ display: "flex" }} key={id}>
<h3 className="item">{name}</h3>
<button className="btn" onClick={() => removeContact(id)}>
Remove item
</button>
</div>
);
})}
<button className="btn" onClick={removeContacts}>
REMOVE ALL CONTACTS
</button>
</div>
);
};
export default ContactList;
Теперь давайте обсудим код по частям, но на этот раз я не буду объяснять каждую строчку, чтобы не повторяться.
const data = [
{id: 0, name: 'Micheal'},
{id: 1, name: 'Ahmet'},
{id: 2, name: 'Daniel'},
]
Выше у нас есть массив объектов, в котором хранятся некоторые данные. Ключами в этих объектах являются id
и name
. Большую часть времени данные будут готовы, и нам не придется иметь дело с указанием идентификаторов, но это просто пример
const [contacts, setContacts] = useState(data);
присваиваем значение contacts
массиву data
.
const removeContacts = () => {
setContacts([]);
};
Я буду использовать функцию removeContacts
для удаления всего в массиве contacts
(напомню, что контакты берутся из data, а data — это массив). Так как мы повторно присваиваем значение с помощью функции setContacts([])
, присвоение пустого массива приведет к удалению всего в массиве. Следовательно, функция removeContacts
удалит все из массива, преобразовав его в пустой массив.
Далее, rmeoveContact
. Как следует из названия, она создана для удаления только одного контакта:
const removeContact = (id) => {
const filteredContacts = contacts.filter((contact) => contact.id !== id);
setContacts(filteredContacts);
};
Функция removeContact(id)
принимает параметр — id
. Когда будет нажата кнопка ‘Remove Item’, она вызовет этот конкретный ‘id’ и отфильтрует (удалит) его. Поскольку в методе фильтрации я задал параметр contact, каждый ‘data’ (у нас есть массив data
) будет представлен как contact
. Логика, стоящая за этим кодом; contacts.filter((contact) => contact.id !== id)
, это сравнивает, если contact.id
и id
не одинаковы. Затем возвращаются элементы с разными id.
Наконец, у нас есть большой return
, вот он:
return (
<div>
{contacts.map(({ id, name }) => {
return (
<div style={{ display: "flex" }} key={id}>
<h3>{name}</h3>
<button onClick={() => removeContact(id)}>
Remove item
</button>
</div>
);
})}
<button onClick={removeContacts}>
REMOVE ALL CONTACTS
</button>
</div>
);
Код выше отображает массив contacts
. Что это за хрень такая contacts.map(({ id, name })
Я сразу же деструктурировал то, что приходит из массива contacts. Если вы понятия не имеете, что это такое, посмотрите эту статью из MDN Web Docs.
Если бы я не деструктурировал его, скажем, сделал это так contacts.map((contact) => { return () })
, то когда я захочу обратиться к контакту, мне пришлось бы обращаться к нему как key={contact.id}
и <h3>{contact.name}</h3>
. С другой стороны, из-за того, что я его деструктурировал, я могу ссылаться так; key={id}
и <h3>{name}</h3>
. Короче говоря, я стараюсь избегать точек (в своем коде) по некоторым причинам… личное предпочтение.
Ну вот, пора поговорить о кнопках:
<button onClick={() => removeContact(id)}>
Remove item
</button>
Как вы можете видеть в коде выше, у нас есть слушатель события onClick
, который идет для функции removeContact(id)
. Таким образом, именно отсюда мы получаем id. Подождите, как он получает id????? Вот как contacts.map(({ id, name })
. Вспомните, мы деструктурировали его таким образом.
Наконец,
<button className="btn" onClick={removeContacts}>
REMOVE ALL CONTACTS
</button>
Код выше вызывает функцию removeContact
по щелчку. Она просто переоценивает наш массив data
в пустой массив.
Я бы продолжил писать, но этот пост становится слишком длинным по сравнению с другими моими постами. Итак, в следующей части я расскажу об использовании объектов в качестве начальных значений с помощью хуков.