useState — широко используемый хук в React. Почти каждый компонент, который вы разрабатываете в React, включает в себя состояние. В этом посте я собираюсь показать вам четыре различных варианта использования хука useState.

Я предполагаю, что у вас есть базовые знания о React и состоянии. Если нет, посетите документы, чтобы начать.

Состояние инициализации

Напомню, я расскажу, как инициализировать состояние. Сначала импортируйте useState, а затем объявите переменные состояния следующим образом.

import { useState } from 'react'
const [name, setName] = useState('kunal')

setName — это функция, используемая для установки состояния, т. е. name. Он имеет значение по умолчанию.

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

Теперь давайте рассмотрим некоторые варианты использования.

1. Условный рендеринг

Допустим, в вашем приложении есть пользователь, и вы хотите отобразить что-то в зависимости от того, является ли пользователь администратором. Вы можете сделать это с помощью условного рендеринга.

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

const [user, setUser] = useState({
    name: 'kunal',
    isAdmin: false
})  

Теперь визуализируйте записи. tableData содержит записи для отображения.

return (
  <div>
      <table>
          <tr>
              <th>id</th>
              <th>First Name</th>
              <th>City</th>
              {user.isAdmin &&  <th>Action</th>}
          </tr>
          {tableData.map(data => (
              <tr>
                  <td> {data.id} </td>
                  <td> {data.first_name} </td>
                  <td> {data.city} </td>
                  {user.isAdmin &&  
                      <td>
                          <button> Edit </button>
                      </td>
                  }

              </tr>
          ))}
      </table>
  </div>
)

Здесь обычный пользователь увидит только первые три столбца. Однако пользователь с правами администратора также увидит 4-й столбец, содержащий кнопку «Изменить».

Если атрибут isAdmin равен false, столбец не будет виден.

Возьмем другой пример. У вас есть две таблицы, и вы хотите отображать только одну за раз.

У нас есть состояние toggleTable, которое решает, какую таблицу отображать. Вы можете переключаться между столами одним нажатием кнопки.

const [toggleTables, setToggleTables] = useState(false)

Две таблицы показывают разные данные и могут быть отображены в соответствии со значением состояния с помощью условного выражения.

return (
    <div>
        <div>
            <button onClick={handleClick} >
                Show the other table
            </button>
        </div>
        <div>
            {
                toggleTables ? 
            
                    <table>
                        <tr>
                            <th>id</th>
                            <th>First Name</th>
                            <th>Last Name</th>
                            <th>City</th>
                        </tr>
                        {tableData1.map(data => (
                            <tr>
                                <td> {data.id} </td>
                                <td> {data.first_name} </td>
                                <td> {data.last_name} </td>
                                <td> {data.city} </td>

                            </tr>
                        ))}
                    </table>
                :  
                    <table>
                        <tr>
                            <th>id</th>
                            <th>First Name</th>
                            <th>City</th>
                            <th>Bitcoin Address</th>
                            <th>Credit Card</th>
                            <th>Card Type</th>
                            <th>Currency</th>
                        </tr>
                        {tableData2.map(data => (
                            <tr>
                                <td> {data.id} </td>
                                <td> {data.first_name} </td>
                                <td> {data.city} </td>
                                <td> {data.bitcoin_address} </td>
                                <td> {data.credit_card} </td>
                                <td> {data.card_type} </td>
                                <td> {data.currency} </td>
                            </tr>
                        ))}
                    </table>
            } 
        </div>                 
    </div>
  )

А вот функция handleClick, в которой мы меняем состояние.

const handleClick = () => {
    setToggleTables(!toggleTables);
}

2. Счетчик

Состояние также можно использовать для реализации счетчика. Это включает в себя отслеживание предыдущего состояния. Во-первых, подсчет как состояние со значением по умолчанию 0.

const [count, setCount] = useState(0)  

Затем отрендерите то же самое и получите две кнопки для увеличения и уменьшения с обработчиками onClick.

<h2> {count} </h2>
<div>
    <button onClick={() => { setCounter(-1) }} > Decrement </button>
    <button onClick={() => { setCounter(1) }}> Increment </button>
</div>

Реализуйте функцию обработчика.

function setCounter(value) {
    setCount(count+value);
}

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

<div>
    <form onSubmit={handleSubmit}>
        <label> Enter a value to increment by </label>
        <input type='number' />
        <button type='submit' > Submit </button>
    </form>
</div>

Реализуйте функцию обработчика. Используйте ту же функцию setCounter, чтобы установить значение состояния в соответствии со значением, заданным пользователем.

const handleSubmit = (event) => {
    event.preventDefault();
    setCounter(parseInt(event.target[0].value));
}

Используйте event.preventDefault() при отправке формы. Об этом подробнее здесь".

3. Обработка форм

Обработка форм — очень важный вариант использования хука useState. Вы столкнетесь с этим повсюду.

Давайте создадим базовую форму со следующими полями. Сделайте каждое поле необходимым.

 <form onSubmit={handleSubmit}>
        <input placeholder='Enter name' 
               onChange={(e) => {setName(e.target.value)}} 
               value={name} required/>        
        <br/>
        <input type='email' placeholder='Enter email' value={email}
                 onChange={(e) => {setEmail(e.target.value)}} required/>
        <br/>
        <input type='password' placeholder='Enter password' value={password}
                 onChange={(e) => {setPassword(e.target.value)}} required/>
        <br/>
        <label>Gender</label>
        <select onChange={(e) => {setGender(e.target.value)}} value={gender}
                required>
            <option>Male</option>
            <option>Female</option>
        </select>
        <br/>

        <button type='submit'>Submit</button>

</form>

Определите следующие переменные состояния для того же самого.

const [name, setName] = useState('')
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const [gender, setGender] = useState('')

Эти переменные состояния содержат значения полей формы. Вы хотите, чтобы они обновлялись вместе с пользовательским вводом. Это делается с помощью атрибута onChange элемента ввода.

В приложениях реального времени отправка форм обычно занимает некоторое время. Итак, важно показать пользователю, что форма отправляется. Вы можете сделать это, используя другую переменную состояния.

const [isSubmitting, setIsSubmitting] = useState(false)

Как только кнопка отправки будет нажата, установите isSubmitting как true, а затем установите его на false после отправки. Тем временем покажите пользователю сообщение. Здесь нет ничего, что могло бы задержать отправку формы, поэтому вы не сможете увидеть сообщение.

Давайте смоделируем это поведение.

const handleSubmit = (event) => {
    event.preventDefault();
    
    setIsSubmitting(true)
    setTimeout(() => {
        setIsSubmitting(false);
        alert("Form submission successful")
    }, 3000);
}

Используйте setTimeout, чтобы подождать несколько секунд, прежде чем форма будет отправлена. И отобразите сообщение прямо под кнопкой отправки.

{isSubmitting && 'Submitting...'}

4. Список дел

Один из самых простых вариантов использования хука useState — простой список дел. Я собираюсь показать вам, как реализовать функции добавления, обновления и удаления.

Во-первых, иметь поле ввода и кнопку для добавления задачи. Держите пользовательский ввод в состоянии.

const [taskInput, setTaskInput] = useState('')
<input type='text' placeholder="Name your task" value={taskInput}
                    onChange={(e) => { setTaskInput(e.target.value) }}/>
<button onClick={handleSubmit} >Add item</button>

Кроме того, у вас есть состояние для хранения всего списка дел.

const [todoList, setTodoList] = useState([])

Теперь реализуйте функцию handleClick кнопки «Добавить».

const handleSubmit = () => {
    const newTodo = {
        id: new Date().getTime(),
        task: taskInput,
        updateFlag: false
    }
    setTodoList([...todoList, newTodo]);
    setTaskInput('')
}

Создайте новый объект todo с текущей меткой времени в качестве id. Поле updateFlag определяет, обновляется ли текущий элемент. Теперь отобразите список с параметрами обновления и удаления.

<ul>
  {todoList.map(todo => (
      <li key={todo.id}>
          {todo.task}
          <button onClick={() => {handleUpdate(todo.id)}}>Update</button>
          <button onClick={() => {handleDelete(todo.id)}}>Delete</button>
      </li>
  ))}
</ul>

Для handleDelete используйте метод фильтра, чтобы удалить элемент из массива состояний на основе id (очень важно, чтобы он был уникальным).

function handleDelete(id) {
     setTodoList(todoList.filter(todo =>  todo.id !== id));
}

Чтобы обновить элемент, пользователю необходимо поле ввода для ввода обновленного значения. Итак, используйте updateFlag для переключения между отображением и обновлением элемента. Для каждого элемента в списке выполните следующие действия:

{todo.updateFlag == true
    ? <input type='text' defaultValue={todo.task} 
            onChange={(e) => { setUpdateTaskInput(e.target.value) }}/>
    : todo.task
}

Кроме того, есть еще одна переменная состояния для хранения обновленного входного значения.

const [updateTaskInput, setUpdateTaskInput] = useState()

Если updateFlag истинно, элемент отображает форму для ввода нового значения.

Теперь реализуйте функцию handleUpdate. Функция принимает id из todo в качестве параметра. Вернитесь назад, если обновленное значение пусто.

function handleUpdate(id) {
    if(updateTaskInput == '') return;
          ...
}

Обновление здесь включает изменение отдельного поля объекта. Во-первых, получите элемент из списка, используя id, и создайте другой список, который отфильтрует этот элемент.

const todo = todoList.find(todo => todo.id === id)
const updatedList = todoList.filter(todo =>  todo.id !== id)

Теперь, если updateFlag ложно, установите его как истину, чтобы отобразить поле ввода.

if(todo.updateFlag == false) {
    updatedList.push({...todo, updateFlag: true})
    setTodoList(updatedList)
    return;
}

Теперь, после ввода нового значения, пользователь снова нажимает кнопку обновления. Обновите имя задачи в той же функции, но в противоположном условии.

updatedList.push({...todo, 
    task: updateTaskInput,
    updateFlag: false
})

setTodoList(updatedList);

setUpdateTaskInput('') 

Вы можете найти код в моем репозитории Git.

Заключение

В этой статье я показал вам различные примеры, где вы можете использовать хук useState. Вы будете часто сталкиваться с первыми тремя вариантами использования в своих проектах React.

Четвертый — очень распространенный пример, показывающий, как обрабатывать обновления состояния в различных сценариях. Дайте мне знать, если что-то не так.

Если вы не можете понять содержание или считаете объяснение неудовлетворительным, прокомментируйте свои мысли ниже. Новые идеи всегда приветствуются! Дайте несколько хлопков, если вам понравился этот пост. Подпишитесь и подпишитесь на меня, чтобы получать еженедельные материалы. Пишите мне в LinkedIn, если хотите что-то обсудить. А пока, До свидания!

Повышение уровня кодирования

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

  • 👏 Хлопайте за историю и подписывайтесь на автора 👉
  • 📰 Смотрите больше контента в публикации Level Up Coding
  • 🔔 Подписывайтесь на нас: Twitter | ЛинкедИн | "Новостная рассылка"

🚀👉 Присоединяйтесь к коллективу талантов Level Up и найдите прекрасную работу