В предыдущей статье ‹link› вы узнали, как настроить свою первую среду React и запустить приложение с помощью CRA.
useState
— это хук в React, который позволяет вам добавлять состояние к функциональным компонентам. Он возвращает пару значений: текущее состояние и функцию, которую можно использовать для обновления состояния. Вот пример того, как вы можете использовать useState
для добавления части состояния с именем message
к функциональному компоненту:
import React, { useState } from 'react'; function MyComponent() { const [message, setMessage] = useState('Hello World'); return ( <div> <p>{message}</p> <button onClick={() => setMessage('Hello from the button!')}> Update message </button> </div> ); }
В этом примере message
— это текущее значение состояния, а setMessage
— это функция, которую можно использовать для обновления значения message
. В качестве начального состояния мы используем строку «Hello World», хотя начальное состояние не нужно определять, вместо этого вы можете использовать тип (строка, логическое значение, массив и т. д.). Итак, если мы собираемся установить тип для message
, это будет просто useState('')
.
При нажатии кнопки вызывается функция setMessage
с новым значением для message
, которое обновляет состояние и вызывает повторную визуализацию компонента с новым значением.
Важно отметить, что useState
следует вызывать внутри тела функционального компонента, а не в области видимости верхнего уровня или в любой другой части кода.
Предостережения useState
- при использовании
useState
заключается в том, что обновление состояния может быть применено не сразу. Это может быть проблемой, если вы полагаетесь на обновленное значение состояния в той же функции или блоке кода, где вы вызываете функцию обновления состояния. - Например, рассмотрим следующий код:
const [count, setCount] = useState(0); function increment() { setCount(count + 1); console.log(count); // Logs 0, not 1 }
В этом примере функция increment
увеличивает значение count
на 1, но обновление состояния может быть применено не сразу. Это означает, что оператор console.log
будет регистрировать старое значение count
, а не обновленное значение.
Чтобы обойти эту проблему, вы можете использовать второй аргумент функции setState
, который представляет собой обратный вызов, который будет выполняться после применения обновления состояния. Например:
function increment() { setCount(count + 1, () => { console.log(count); // Logs the updated value of count }); }
Кроме того, вы можете использовать хук useEffect
для выполнения действия после применения обновления состояния. Например:
useEffect(() => { console.log(count); // Logs the updated value of count }, [count]);
- Состояние, возвращаемое
useState
, всегда является одним значением. Если вам нужно сохранить несколько значений в состоянии, вы можете использовать объект или массив для хранения значений и оператора расширения для их обновления. Например:
const [state, setState] = useState({ count: 0, message: 'Hello World' }); setState({ ...state, count: state.count + 1 }) console.log(state) // count: 1, message: 'Hello World'
Если бы вы собирались только обновить счетчик, не копируя предыдущее состояние, то состояние сообщения было бы удалено.
setState({ count: state.count + 1 }) console.log(state) // count: 1
useState
работает только с простыми значениями (числа, строки, логические значения и т. д.). Если вам нужно хранить более сложные значения в состоянии (например, объекты или массивы), вы должны быть осторожны, чтобы не изменять их напрямую, потому что это может привести к непредвиденному поведению. Вместо этого вы должны создать новую копию значения и обновить состояние новой копией. Например:
const [items, setItems] = useState([1, 2, 3]); const newItems = [...items, 4]; setItems(newItems) console.log(items) // [1,2,3,4]
И без оператора распространения:
const [items, setItems] = useState([1, 2, 3]); const newItems = [4]; setItems(newItems) console.log(items) // [4]
useState
следует использовать только для значений, которые изменяются внутри компонента. Если вам нужно сохранить значения, поступающие извне компонента (например, свойства или контекст), вы должны использовать хукuseEffect
для обновления состояния при изменении значений. КрюкuseEffect
будет рассмотрен в следующей статье!
Практическое задание
А теперь пришло время лучше запомнить собранную информацию, для этого я создал очень простое и короткое задание, которое поможет вам закрепить знания в области useState
.
- В своем репозитории создайте функциональный компонент с именем
Counter
. Откройте файлsrc/App.js
и импортируйте вновь созданный компонент и хукuseState
из пакетаreact
. - В компоненте
Counter
вызовите хукuseState
, вы можете вызвать значенияcount
иsetCount
. Начальное значение счетчика должно быть 0. - В JSX отобразите текущее значение
count
и добавьте обработчикonClick
к кнопке, которая увеличивает значениеcount
с помощью функции обновления, возвращаемойuseState
. - Если это было слишком просто, добавьте еще два обработчика в свой
Counter
. Первый для уменьшения текущего значенияcount
value, а второй для сброса значения счетчика в начальное состояние.
Вот как должен выглядеть компонент Counter
(базовый):
import React, { useState } from 'react'; function Counter() { const [count, setCount] = useState(0); return ( <div> <button onClick={() => setCount(count + 1)}> Increment </button> <p>Count: {count}</p> </div> );
Бонус:
import React, { useState } from 'react'; const INIT_STATE = 0; function Counter() { const [count, setCount] = useState(INIT_STATE); return ( <div> <button onClick={() => setCount(count + 1)}> Increment </button> <button onClick={() => setCount(count - 1)}> Decrement </button> <button onClick={() => setCount(INIT_STATE)}> Reset </button> <p>Count: {count}</p> </div> );
Надеюсь, вам было легко понять, как работает useState
. В следующей статье я расскажу о крючке useEffect
.