В React управление состоянием компонентов всегда было проблемой. Традиционно использовались компонент класса и подход жизненного цикла, но этот подход приводит к избыточному коду, который трудно поддерживать. Появление React Hooks решает эту проблему, позволяя нам реализовать управление состоянием аналогично компонентам классов в функциональных компонентах. В этой статье я покажу вам, как использовать React Hooks для реализации управления состоянием сложных компонентов.
Основы управления состоянием — useState Hook
UseState — один из наиболее часто используемых хуков, которые позволяют нам определять состояние в функциональном компоненте и обновлять его в компоненте. Вот простой пример:
import { useState } from 'react'; function Counter() { const [count, setCount] = useState(0); function increment() { setCount(count + 1); } return ( <div> <p>Count: {count}</p> <button onClick={increment}>Increment</button> </div> ); }
В приведенном выше коде мы определяем состояние счетчика с помощью useState и обновляем его с помощью метода setCount. Каждый раз, когда нажимается кнопка Increment, значение count увеличивается на 1.
Расширенный уровень управления состоянием — useReducer Hook
Когда состояние компонента сложное, использование useState может привести к путанице в коде. На этом этапе рассмотрите возможность использования useReducer. UseReducer — это еще один способ управления состоянием, который позволяет нам лучше организовать наш код и поместить логику для обновления состояния внутри функции редуктора.
import { useReducer } from 'react'; const initialState = { count: 0 }; function reducer(state, action) { switch (action.type) { case 'increment': return { count: state.count + 1 }; case 'decrement': return { count: state.count - 1 }; default: throw new Error(); } } function Counter() { const [state, dispatch] = useReducer(reducer, initialState); return ( <div> <p>Count: {state.count}</p> <button onClick={() => dispatch({ type: 'increment' })}>Increment</button> <button onClick={() => dispatch({ type: 'decrement' })}>Decrement</button> </div> ); }
В приведенном выше коде мы определяем счетчик состояний с помощью useReducer и помещаем логику обновления состояния в функцию редуктора. Каждый раз, когда нажимается кнопка «Увеличить» или «Уменьшить», запускается соответствующее действие.
Практика — реализация TodoList с использованием React Hooks
После введения useState и useReducer выше, давайте реализуем компонент TodoList. Этот компонент имеет следующие функции:
- Отображает все элементы списка задач
- Добавить новый элемент списка дел
- Удалить выполненный элемент задачи
Во-первых, нам нужно определить компонент TodoItem, который отображает задачу для каждого элемента.
function TodoItem({ text, completed, onClick }) { return ( <li style={{ textDecoration: completed ? 'line-through' : 'none' }} onClick={onClick}> {text} </li> ); }
Далее мы можем начать писать компонент TodoList. Поскольку нам нужно управлять состоянием нескольких элементов todo, более уместно использовать useReducer.
import { useReducer } from 'react'; import TodoItem from './TodoItem'; const ADD_TODO = 'ADD_TODO'; const TOGGLE_TODO = 'TOGGLE_TODO'; const DELETE_TODO = 'DELETE_TODO'; function reducer(state, action) { switch (action.type) { case ADD_TODO: return [ ...state, { id: state.length + 1, text: action.text, completed: false, }, ]; case TOGGLE_TODO: return state.map(todo => todo.id === action.id ? { ...todo, completed: !todo.completed } : todo ); case DELETE_TODO: return state.filter(todo => todo.id !== action.id); default: throw new Error(); } } export default function TodoList() { const [state, dispatch] = useReducer(reducer, []); function handleAdd(text) { dispatch({ type: ADD_TODO, text }); } function handleToggle(id) { dispatch({ type: TOGGLE_TODO, id }); } function handleDelete(id) { dispatch({ type: DELETE_TODO, id }); } return ( <div> <ul> {state.map(todo => ( <TodoItem key={todo.id} text={todo.text} completed={todo.completed} onClick={() => handleToggle(todo.id)} /> ))} </ul> <input type="text" placeholder="Add a new todo" onKeyDown={e => e.key === 'Enter' && handleAdd(e.target.value)} /> <button onClick={() => handleDelete()}>Delete Completed Todos</button> </div> ); }
В приведенном выше коде мы определяем три типа действий, соответствующих разным операциям, и обрабатываем соответствующую логику в функции редуктора. В компоненте TodoList мы определяем состояние задач с помощью useReducer и предоставляем три метода handleAdd, handleToggle и handleDelete для добавления, переключения и удаления элементов задач. В то же время мы также отображаем элемент ввода и элемент кнопки для добавления новых элементов списка задач и удаления завершенных элементов списка задач соответственно.
На данный момент мы реализовали простой компонент TodoList. Использование useReduce позволяет нам лучше организовать наш код и сделать его более понятным.
Краткое содержание
React Hooks обеспечивают более лаконичный способ управления состоянием компонентов. Использование useState и useReduce позволяет нам лучше организовать наш код и улучшить его читабельность и удобство сопровождения.
Дополнительные материалы на PlainEnglish.io.
Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Подпишитесь на нас в Twitter, LinkedIn, YouTube и Discord .
Заинтересованы в масштабировании запуска вашего программного обеспечения? Ознакомьтесь с разделом Схема.