Давайте сначала разберемся с состоянием в React.

Состояние можно представить как данные или свойство, которые используются в приложении. Эти значения данных/свойств, вероятно, изменятся со временем, и хук State в React помогает нам отслеживать и управлять изменяющимися состояниями.

Чтобы использовать хук State, нам нужно импортировать его, как показано ниже:

import React, {useState} from 'react'

Затем мы можем вызвать useState() внутри функции компонента и передать начальное состояние (это значение может быть любого типа, такого как строка, число или объект) в качестве аргумента:

const [count, setCountValue] = useState(0);

Хук useState() возвращает массив, где первый элемент соответствует текущему состоянию, а второй элемент — функция, которая позволяет нам обновить текущее состояние.

Приступаем к строительству 🏗️

Рассмотрим код простой функциональности счетчика —

import React, {useState} from 'react'

const App = () => {

    const [count, setCountValue] = useState(1)

    const decrement = () => {
        setCountValue(prevState => {
            prevState-1
        })
    }

    const increment = () => {
        setCountValue(prevState => {
            prevState+1
        })
    }

    return(
        <div>
            <button onClick={decrement}> - </button>
            <span> {count} </span>
            <button onClick={increment}> + </button>
        </div>
    )
}

export default App;

Упрощение приведенного выше кода…

useState() вызывается внутри функции компонента, и ей передается начальное состояние (1). Это означает, что когда компонент отображается в первый раз (когда страница загружается изначально), счетчик устанавливается на 1.

Как упоминалось ранее, useState() возвращает массив из двух элементов. Здесь, используя разрушение массива, текущее состояние сохраняется в переменной count, а функция для обновления текущего состояния — setCountValue.

Кнопка + запускает функцию увеличения, а - запускает функцию уменьшения. Я использую функцию setCountValue для обновления текущего значения состояния.

Давайте посмотрим на распространенную ошибку, которую склонны совершать разработчики при попытке обновить состояние, используя предыдущее состояние:

const decrement = () => {
        setCountValue(count - 1)
    }

Почему приведенный выше подход является неправильным для обновления значения состояния?
Когда мы изменяем состояние, используя предыдущее значение состояния (в приведенном выше коде мы напрямую используем переменную count), мы должны использовать функциональную версию установки состояние, как показано ниже.

const decrement = () => {
        setCountValue(prevState => {
            prevState-1
        })
    }

prevState — это предыдущий снимок состояния, который предоставляет React. Причина использования этого подхода заключается в том, что функция обновления состояния в React планирует обновление состояния. Используя версию функции для установки состояния, мы можем гарантировать, что предыдущее состояние всегда обновляется (последнее).

Погружаемся глубже в useState()

Каждый раз, когда вызывается функция обновления состояния, состояние обновляется, и функция компонента, из которой инициализируется useState(), выполняется снова.

Также важно помнить, что useState() регистрирует разные состояния для каждого экземпляра компонента, а React управляет состояниями независимо для каждого компонента.

Вот два часто задаваемых вопроса при использовании useState():

  1. Почему useState() использует const, так как значение состояния обновляется?
    → Способ обдумать этот вопрос состоит в том, что каждый раз, когда компонент визуализируется (вызывается функция обновления состояния), где-то создается и управляется новая переменная иначе, внутренне, React.
  2. Не переопределяет ли состояние по умолчанию текущее значение состояния каждый раз, когда вызывается функция обновления состояния и визуализируется компонент?
    → React отслеживает первый экземпляр, в котором был вызван useState(), и предотвращает любую перезапись состояния по умолчанию во время последующего рендеринга компонента. .

Еще одна важная концепция для понимания — как работать с объектами и useState():

const [state, setState] = useState({count:4, toggle:'Yes'})
    const count = state.count
    const toggle = state.toggle

    function decrement() {
        setState((prevState) => {
            return ({
                count: prevState.count-1
            })
        })
    }

Приведенный выше код неверен, поскольку функция обновления setState переопределяет предыдущее состояние только с обновленным счетчиком (переключатель: «Да» удален).

Правильный способ использования объекта — расширить предыдущее состояние, а затем установить новое состояние.

function decrement() {
        setState((prevState) => {
            return ({
                ...prevState,
                count: prevState.count-1
            })
        })
    }

Наконец, давайте поговорим о расширенной концепции использования useState().

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

Следовательно, есть другой способ передать состояние в useState(), версию функции.
useState(() => {return 4})

Подход запускает функцию начального состояния только во время рендеринга первого компонента. Этот подход предпочтительнее, когда у нас есть начальное состояние с интенсивными вычислениями.

Спектр информации вокруг useState() может быть ошеломляющим 🤯. Не забывайте идти медленно и понимать концепции, как если бы вы строили базу 💪 в React.