Хук useState

Последнее обновление: 01.04.2022

Одним из наиболее используемых встроенных хуков является useState, который позволяет определить состояние компонента. Например, определим простейший компонент, который применяет этот хук:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>METANIT.COM</title>
</head>
<body>
    <div id="app"></div>
       
    <script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
    <script type="text/babel">
	
	function Counter() {
	  const [count, setCount] = React.useState(0);
	  return (
		<div>
		  <h3>Count = {count}</h3>
		  <button onClick={() => setCount(count + 1)}>
			Увеличить
		  </button>
		</div>
	  );
	}
          
	ReactDOM.createRoot(
        document.getElementById("app")
  )
  .render(
		<Counter />
	)
    </script>
</body>
</html>

Итак, здесь определен компонент Counter, причем определен в виде функции, так как мы не можем использовать хуки в классах-компонентах.

Вначале определяем переменные состояния:

const [count, setCount] = React.useState(0);

В данном случае определяются две переменных: count и setCount. Переменная count собственно хранит состояние - некоторый объект, а переменная setCount представляет функцию, которая позволяет изменять значение переменной count.

Несмотря на то, что между названиями переменных есть связь - count и setCount, однако это не более чем условность. Названия переменных могут быть вообще никак между собой не связаны.

Что за значение будет хранить переменная count? А хранит она то значение, которое передается в функцию useState() - в данном случае это число 0.

Чтобы инспектировать значение переменной count, ее значение выводится в заголовке h3:

<h3>Count = {count}</h3>

В коде компонента определена кнопка, которая по нажатию будет вызывать изменение значения переменной count

onClick={() => setCount(count + 1)}

В данном случае применяется стрелочная функция, которая выполняет выражение setCount(count + 1), которое увеличивает значение count на единицу.

В итоге по нажатию на кнопку изменится значение переменной count:

Хуки hooks в React и useState

Определение переменных состояния

Итак, хук useState определяет переменные состояния. Единственный аргумент хука определяет начальное значение переменной состояния. А возвращает useState() массив из двух объектов. Первый объект представляет значение состояния, а второй объект представляет функцию, которая обновляет это значение. Например, выше состояние определялось следующим образом:

const [count, setCount] = React.useState(0);

В данном случае для определения переменных применяется синтаксис декомпозиции или destructuring. Но также мы могли бы использовать и стандартный синтаксис массивов для получения значений переменных:

var countStateArray= React.useState(0);
var count = countStateArray[0];
var setCount = countStateArray[1];

Определение нескольких переменных состояния

При необходимости можно определять множество переменных состояния. Например:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>METANIT.COM</title>
</head>
<body>
    <div id="app"></div>
        
    <script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
    <script type="text/babel">
     
    function User() {
      const [name, setName] = React.useState("Tom");
      const [age, setAge] = React.useState(36);
	  
      return (
        <div>
          <h3>Имя: {name}</h3>
          <h3>Возраст: {age}</h3>
        </div>
      );
    }
           
    ReactDOM.createRoot(
        document.getElementById("app")
    )
    .render(
        <User />
    );
    </script>
</body>
</html>

В данном случае определены две переменных состояния: name и age.

Хук useState в React и определение переменных

Также мы можем изменять значения этих переменных. Например, добавим к предыдущему примеру изменение переменных:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>METANIT.COM</title>
</head>
<body>
    <div id="app"></div>
        
    <script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
    <script type="text/babel">
     
    function User() {
      const [name, setName] = React.useState("Tom");
      const [age, setAge] = React.useState(36);
	  
	  function handleNameChange(event) {    
		setName(event.target.value);  
	 }
	  
	  function handleAgeChange(event) {    
		setAge(event.target.value);  
	 }
      return (
        <div>
          <h3>Имя: {name}</h3>
          <h3>Возраст: {age}</h3>
		  
		  <div>
			<p>Имя: <input type="text" value={name} onChange={handleNameChange} /></p>
			<p>Возраст: <input type="number" min="0" max="110" value={age} onChange={handleAgeChange} /></p>
		  </div>
        </div>
      );
    }
           
    ReactDOM.createRoot(
        document.getElementById("app")
    )
    .render(
        <User />
    );
    </script>
</body>
</html>

В данном случае для обновления значений переменных name и age в компоненте определены два поля ввода. Событие onChange каждого поля привязано к одной из функций компонента - handleAgeChange или handleNameChange. Поэтому изменение значения в каждом поле вызовет соответствующую функцию. Например, при вводе текста для имени пользователя будет вызываться функция handleNameChange():

function handleNameChange(event) {    
	setName(event.target.value);  
}

По умолчанию в функцию обработки события поля ввода input передается информация о событии, из которой с помощью свойства target.value мы можем получить введенное значение и затем передать его в функцию изменения состояния: setName(event.target.value)

Hook useState в React и определение переменных

Однако нам необязательно определять отдельные переменные для хранения состояния. Хук useState равным образом позволяет определять массивы и комплексные объекты. Например, перепишем предыдущий пример, объединив переменные в один объект:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>METANIT.COM</title>
</head>
<body>
    <div id="app"></div>
        
    <script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
    <script type="text/babel">
     
    function UserData() {
      const [user, setUser] = React.useState({name:"Tom", age: 36});
	  
	  function handleNameChange(event) { 
		setUser({name: event.target.value, age: user.age});   
	 }
	  
	  function handleAgeChange(event) {   
		setUser({name: user.name, age: event.target.value});   
	 }
      return (
        <div>
          <h3>Имя: {user.name}</h3>
          <h3>Возраст: {user.age}</h3>
		  
		  <div>
			<p>Имя: <input type="text" value={user.name} onChange={handleNameChange} /></p>
			<p>Возраст: <input type="number" min="0" max="110" value={user.age} onChange={handleAgeChange} /></p>
		  </div>
        </div>
      );
    }
           
    ReactDOM.createRoot(
        document.getElementById("app")
    )
    .render(
        <UserData />
    )
    </script>
</body>
</html>

Здесь состояние компонента представлено сложным объектом, который имеет два свойства: name и age. Но в данном случае при обновлении следует учитывать, что функция обновления (в данном случае - setUser) полностью изменяет хранимое значение состояния, поэтому нам надо полностью переопределить его свойства:

setUser({name: event.target.value, age: user.age});

В итоге мы получим тот же результат:

Hook useState в React и определение переменных

Однако если у нас объект имеет множество свойств, то перечисление всех свойств и их значений может быть утомительным. И в этом случае мы можем сократить запись с помощью spread-оператора ...:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>METANIT.COM</title>
</head>
<body>
    <div id="app"></div>
        
    <script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
    <script type="text/babel">
     
    function UserData() {
      const [user, setUser] = React.useState({name:"Tom", age: 36});
	  
	  function handleNameChange(event) { 
		setUser({...user, name: event.target.value});   
	 }
	  
	  function handleAgeChange(event) {   
		setUser({...user, age: event.target.value});   
	 }
      return (
        <div>
          <h3>Имя: {user.name}</h3>
          <h3>Возраст: {user.age}</h3>
		  
		  <div>
			<p>Имя: <input type="text" value={user.name} onChange={handleNameChange} /></p>
			<p>Возраст: <input type="number" min="0" max="110" value={user.age} onChange={handleAgeChange} /></p>
		  </div>
        </div>
      );
    }
           
    ReactDOM.createRoot(
        document.getElementById("app")
    )
    .render(
        <UserData />
    );
    </script>
</body>
</html>
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850