Использование состояния в ваших компонентах функции React
Что такое крючок?
React Hooks - это функции, которые позволяют нам работать с функциями состояния и жизненного цикла в компонентах функций React. Раньше это было возможно только при использовании классов, но хуки дают нам альтернативный способ использования этих важных функций класса вне классов.
Что такое useState?
Перехватчик состояния (useState) - это наиболее часто используемый перехватчик для создания компонентов React - он позволяет нам добавлять состояние к нашим функциональным компонентам без необходимости преобразовывать их в классы.
Использование состояния в обычном компоненте класса React:
class MyClass extends React.Component {
constructor(props) {
super(props);
this.state = {
name: 'Medium'
};
}
Использование состояния в компоненте функции React:
import React, { useState } from 'react';
function MyFunction() {
const [name, setName] = useState('Medium');
}
Мы импортируем useState из библиотеки React, как показано выше. Функция useState () возвращает массив, содержащий два значения:
- Текущее состояние = текущее значение нашего состояния (в нашем примере мы назначаем это константному имени)
- State Setter = функция, используемая для обновления нашего состояния (обычно присваивается константе с тем же именем, что и текущее состояние, с префиксом «set» с верблюжьей оболочкой, например, setName)
Теперь, каждый раз, когда мы хотим обновить наше состояние, мы просто вызываем функцию установки состояния, и это сигнализирует React, что мы хотели бы повторно отрендерить наш компонент с его обновленным состоянием.
Состояние инициализации
При назначении нашего текущего состояния мы можем столкнуться с проблемами, если наше начальное состояние не инициализировано. Если мы попытаемся получить доступ к нашему состоянию после первоначального рендеринга, но перед повторным рендерингом, мы обнаружим, что наше состояние «undefined».
Неинициализировано:
const [name, setName] = useState();
Вышеупомянутое присвоение не инициализирует состояние нашего имени, и если оно будет вызвано перед использованием нашей функции установки состояния, оно просто вернет «undefined». Чтобы бороться с этим, мы инициализируем наше состояние как аргумент в вызове функции useState ().
Инициализировано:
const [name, setName] = useState('Medium');
Теперь, вызывая наше состояние имени после первоначального рендеринга, мы получим начальное состояние «Среднее» в качестве нашего имени. Теперь, когда мы меняем состояние, наше новое значение просто переопределяет предыдущее начальное состояние.
Примечание: это не обязательно должна быть строка, это может быть любое начальное состояние, которое вам нравится (например, число, логическое значение, объект, массив и т. д.). Его можно даже инициализировать как пустые строки, объекты и т. д.)
Использование состояния
В случае с компонентами класса для доступа к нашему состоянию необходимо вызвать this.state:
<h1>Hello, {this.state.name}.</h1>
С функциональными компонентами нам больше не нужно беспокоиться об использовании this.state и мы можем напрямую отображать наше состояние следующим образом:
<h1>Hello, {name}.</h1>
Возврат: Здравствуйте, средний.
Это делает наш код намного чище и избавляет нас от неизбежной отладки, когда мы забываем об этом. Это также избавляет нас от необходимости связывать this с любыми функциями, как мы это делаем с компонентами класса.
Обновление состояния
Чтобы обновить наше состояние, мы используем нашу функцию установки состояния (set ___ ()), определенную ранее. В нашем примере это setName:
setName('New Medium');
Это изменяет наше текущее состояние имени на «New Medium» и повторно выполняет рендеринг нашего функционального компонента.
<h1>Hello, {name}.</h1>
Теперь возвращается: Здравствуйте, новый канал.
Обновление из предыдущего состояния
Пример 1. Число
Часто мы хотим, чтобы наше состояние оставалось неизменным, и просто добавляли в него дополнительные данные. Допустим, у нас есть счетчик, который мы хотим увеличивать при нажатии кнопки. В этом случае нам нужно обновить наше состояние с помощью функции обратного вызова. Без функции обратного вызова мы рискуем использовать «устаревшие» значения состояния.
function Counter() {
const [count, setCount] = useState(0);
const increment = () => setCount(prevCount => prevCount + 1);
return (
<div>
<p>Clicks: {count}</p>
<button onClick={increment}>Increment</button>
</div> );
}
В этом примере у нас есть компонент функции счетчика с функцией приращения (обработчик событий), которая вызывает setCount () с помощью функции обратного вызова. Мы передаем prevCount в качестве аргумента, который возвращает prevCount + 1 в качестве нашего обновленного состояния. Мы также можем увидеть, как мы можем использовать обработчики событий в нашем JSX, которые будут вызываться при выполнении таких действий, как нажатие кнопки (см. Атрибут кнопки onClick).
Пример 2: Массив
Теперь предположим, что у нас есть имя, которое мы хотели бы добавить к массиву имен.
function Names() {
const [names, setNames] = useState(['Medium', 'Jeff']);
const addName = (name) {
setNames((prev) => {
return [name, ...prev];
});
};
Здесь у нас есть обработчик событий addName, который принимает имя в качестве аргумента и добавляет его в начало в нашем массиве состояний с помощью setNames. «… Prev» используется для сохранения предыдущего массива состояний, добавляя новое имя в начало (если мы хотим добавить новое имя в конец, мы могли бы иметь [… prev, name]).
Если мы хотим удалить элемент из массива, мы можем использовать метод filter ():
const removeItem = (targetIndex) => {
setNames((prev) => {
return prev.filter((item, index) => index !== targetIndex);
});
};
Здесь мы передаем индекс значения, которое хотим удалить (targetIndex), и устанавливаем наше новое состояние как каждый элемент в предыдущем массиве - за исключением элемента с индексом, который мы хотели бы удалить.
Пример 3: объект
Наконец, допустим, у нас есть объект, содержащий множество деталей о человеке.
function Person() {
const [details, setDetails] = useState({name: 'Medium'});
const handleChange = ({ target }) => {
const {name, value} = target;
setDetails((prev) => ({
...prev,
[name]: value
}));
};
В этом примере мы передаем пару {name: value} в нашу функцию setDetails, которая также использует ... prev для изменения состояния на предыдущий объект с новой парой значений, добавленной к объекту.
Использование отдельных крючков
Когда у нас есть более сложные объекты, становится полезным разделять изменяющиеся данные по разным переменным состояния. Например, если мы хотим сохранить детали фильма, мы могли бы разделить различную информацию о фильме на отдельные состояния.
function Movie() {
const [title, setTitle] = useState('Interstellar');
const [actors, setActors] = useState(['Matthew McConaughey', 'Anne Hathaway']);
const [ratings, setRatings] = useState({
RottenTomatoes: '72%',
IMDb: '86%',
Metacritic: '74%'});
};
Как видите, у нас может быть несколько состояний, что позволяет нам изменять состояние каждого атрибута Movie более быстрым и легким для чтения способом.
Вот и все, теперь вы можете использовать состояние в своих компонентах функции React! Просто помните, что это доступно только при использовании React и не может использоваться в компонентах класса. 😁