Использование хука состояния
Хуки — это новое дополнение в React 16.8. Они позволяют использовать состояние и другие возможности React без написания класса.
На странице введения использовался этот пример для ознакомления с хуками:
import React, { useState } from 'react';
function Example() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
} Мы начнём изучение хуков, сравнивая этот код с эквивалентным примером класса.
Эквивалентный пример с классом
Если вы раньше работали с классами в React, этот код вам должен быть знаком:
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button>
</div>
);
}
} Состояние начинается со значения { count: 0 }, и мы увеличиваем state.count при нажатии пользователем кнопки, вызывая this.setState(). Мы будем использовать фрагменты из этого класса на протяжении всей страницы.
Примечание
Вы можете спросить, почему мы используем счётчик вместо более реалистичного примера. Это делается для того, чтобы сосредоточиться на API, пока мы делаем первые шаги с хуками.
Хуки и функциональные компоненты
Напоминание: функциональные компоненты в React выглядят так:
const Example = (props) => {
// You can use Hooks here!
return <div />;
} или так:
function Example(props) {
// You can use Hooks here!
return <div />;
} Ранее эти компоненты могли быть известны как «бессостоятельные компоненты». Теперь мы вводим возможность использования состояния React из этих компонентов, поэтому мы предпочитаем название «функциональные компоненты».
Хуки не работают внутри классов. Но вы можете использовать их вместо написания классов.
Что такое хук?
Наш новый пример начинается с импорта хука useState из React:
import React, { useState } from 'react';
function Example() {
// ...
} Что такое хук? Хук — это специальная функция, которая позволяет «подключиться» к возможностям React. Например, useState — это хук, который позволяет добавлять состояние React в функциональные компоненты. Мы изучим другие хуки позже.
Когда использовать хук? Если вы пишете функциональный компонент и понимаете, что вам нужно добавить в него состояние, то раньше вам приходилось преобразовывать его в класс. Теперь вы можете использовать хук внутри существующего функционального компонента. Мы сделаем это прямо сейчас!
Примечание:
Существуют определённые правила относительно того, где вы можете и где не можете использовать хуки внутри компонента. Мы изучим их в Правилах хуков.
Объявление переменной состояния
В классе мы инициализируем состояние count значением 0, установив this.state в { count: 0 } в конструкторе:
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
} В функциональном компоненте у нас нет this, поэтому мы не можем назначить или прочитать this.state. Вместо этого мы вызываем хук useState непосредственно внутри компонента:
import React, { useState } from 'react';
function Example() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useState(0);
Что делает вызов useState? Он объявляет «переменную состояния». Наша переменная называется count, но мы могли бы назвать её как угодно, например, banana. Это способ «сохранить» некоторые значения между вызовами функции — useState — это новый способ использования тех же возможностей, что this.state предоставляет в классе. Обычно переменные «исчезают», когда функция завершается, но переменные состояния сохраняются React.
Что мы передаём в useState в качестве аргумента? Единственным аргументом хука useState() является начальное состояние. В отличие от классов, состояние не обязательно должно быть объектом. Мы можем хранить число или строку, если это всё, что нам нужно. В нашем примере нам нужно только число для подсчёта нажатий пользователя, поэтому передайте 0 в качестве начального состояния для нашей переменной. (Если мы хотели бы сохранить два разных значения в состоянии, мы вызывали бы useState() дважды.)
Что возвращает useState? Он возвращает пару значений: текущее состояние и функцию, которая обновляет его. Вот почему мы пишем const [count, setCount] = useState(). Это похоже на this.state.count и this.setState в классе, за исключением того, что вы получаете их в паре. Если вы не знакомы с синтаксисом, который мы использовали, мы вернёмся к этому в нижней части этой страницы.
Теперь, когда мы знаем, что делает хук useState, наш пример должен стать более понятным:
import React, { useState } from 'react';
function Example() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useState(0);
Мы объявляем переменную состояния под названием count, и задаём ей значение 0. React запомнит её текущее значение между перерисовками и передаст последнее значение нашей функции. Если мы хотим обновить текущее count, мы можем вызвать setCount.
Примечание
Вы можете спросить: почему
useStateне названаcreateState?«Создать» не совсем точно, потому что состояние создаётся только в первый раз, когда наш компонент отрисовывается. Во время последующих отрисовок
useStateдаёт нам текущее состояние. В противном случае это не было бы «состоянием» вообще! Также есть причина, по которой имена хуков всегда начинаются сuse. Мы узнаем об этом позже в Правилах хуков.
Чтение состояния
Когда мы хотим отобразить текущий счёт в классе, мы считываем this.state.count:
<p>You clicked {this.state.count} times</p> В функции мы можем использовать count напрямую:
<p>You clicked {count} times</p> Обновление состояния
В классе нам нужно вызвать this.setState() для обновления состояния count:
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button> В функции у нас уже есть setCount и count в качестве переменных, поэтому нам не нужен this:
<button onClick={() => setCount(count + 1)}>
Click me
</button> Краткое изложение
Давайте теперь кратко повторим то, что мы узнали по строкам и проверим наше понимание.
1: import React, { useState } from 'react';
2:
3: function Example() {
4: const [count, setCount] = useState(0);
5:
6: return (
7: <div>
8: <p>You clicked {count} times</p>
9: <button onClick={() => setCount(count + 1)}>
10: Click me
11: </button>
12: </div>
13: );
14: } -
Строка 1: Мы импортируем хук
useStateиз React. Он позволяет хранить локальное состояние в функциональном компоненте. -
Строка 4: Внутри компонента
Exampleмы объявляем новую переменную состояния, вызывая хукuseState. Он возвращает пару значений, которым мы даём имена. Мы называем нашу переменнуюcount, потому что она хранит количество нажатий кнопки. Мы инициализируем её значением ноль, передав0в качестве единственногоuseStateаргумента. Второй возвращаемый элемент — это функция. Она позволяет обновлятьcount, поэтому мы назовём еёsetCount. -
Строка 9: Когда пользователь нажимает кнопку, мы вызываем
setCountс новым значением. React затем повторно отобразит компонентExample, передав новое значениеcountв него.
Это может показаться много на первый взгляд. Не торопитесь! Если вам непонятно объяснение, снова посмотрите на код выше и попробуйте прочитать его сверху вниз. Мы обещаем, что как только вы попытаетесь «забыть», как работает состояние в классах, и посмотрите на этот код свежим взглядом, он станет понятным.
Подсказка: Что означают квадратные скобки?
Вы, возможно, заметили квадратные скобки при объявлении переменной состояния:
const [count, setCount] = useState(0);
Имена слева не являются частью API React. Вы можете назвать свои переменные состояния:
const [fruit, setFruit] = useState('banana'); Этот синтаксис JavaScript называется “разбором массива”. Это означает, что мы создаём две новые переменные fruit и setFruit, где fruit устанавливается на первое значение, возвращаемое useState, а setFruit — на второе. Это эквивалентно следующему коду:
var fruitStateVariable = useState('banana'); // Returns a pair
var fruit = fruitStateVariable[0]; // First item in a pair
var setFruit = fruitStateVariable[1]; // Second item in a pair Когда мы объявляем переменную состояния с помощью useState, она возвращает пару — массив с двумя элементами. Первый элемент — текущее значение, а второй — функция, которая позволяет обновить его. Использование [0] и [1] для доступа к ним немного запутанно, потому что они имеют определённое значение. Вот почему мы используем разбор массива вместо этого.
Примечание
Вы, возможно, хотите узнать, как React понимает, какой компонент
useStateсоответствует, поскольку мы не передаём ничего вродеthisобратно React. Мы ответим на этот вопрос и на многие другие в разделе вопросов и ответов.
Подсказка: использование нескольких переменных состояния
Объявление переменных состояния как пары [something, setSomething] также удобно, потому что позволяет давать разные имена разным переменным состояния, если вы хотите использовать более одной:
function ExampleWithManyStates() {
// Declare multiple state variables!
const [age, setAge] = useState(42);
const [fruit, setFruit] = useState('banana');
const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]); В компоненте выше у нас есть age, fruit, и todos в качестве локальных переменных, и мы можем обновлять их индивидуально:
function handleOrangeClick() {
// Similar to this.setState({ fruit: 'orange' })
setFruit('orange');
} Вам не обязательно использовать много переменных состояния. Переменные состояния могут хранить объекты и массивы, поэтому вы по-прежнему можете группировать связанные данные вместе. Однако, в отличие от this.setState в классе, обновление переменной состояния всегда заменяет её, а не объединяет.
Мы предоставляем больше рекомендаций по разделению независимых переменных состояния в разделе вопросов и ответов.
Дальнейшие шаги
На этой странице мы узнали об одном из хуков, предоставляемых React, под названием useState. Иногда мы будем называть его «хуком состояния». Он позволяет добавлять локальное состояние в функциональные компоненты React — что мы впервые сделали!
Мы также немного больше узнали о хуках. Хуки — это функции, которые позволяют «подключаться» к возможностям React из функциональных компонентов. Их имена всегда начинаются с use, и есть другие хуки, которые мы ещё не видели.
Теперь давайте продолжим, изучив следующий хук: useEffect. Он позволяет выполнять побочные эффекты в компонентах и аналогичен методам жизненного цикла в классах.
© 2013–present Facebook Inc.
Licensed under the Creative Commons Attribution 4.0 International Public License.
https://17.reactjs.org/docs/hooks-state.html