Попробуйте использовать useReducer вместо useState

React.js

оригинал:useReducer, don't useState

Сложность этой статьи: начальный уровень

По умолчанию у вас уже есть общее представление о React Hooks в этой статье.Если вы не понимаете, вы можете сначала взглянуть.Документация для ReactJS.

Когда разработчики начали использовать API React Hooks в своих приложениях, многие начали использовать useState в качестве инструмента управления состоянием. Однако я твердо уверен, что useReducer лучше подходит для управления состоянием, чем useState.

Сначала позвольте мне определить, что означает «более подходящий»:

  • Легче управлять большими объемами состояния
  • Легче понять другим разработчикам
  • легче проверить

Далее я подробно остановлюсь на трех моментах соответственно.

Управление большим количеством состояний

Большинство мнений в этой статье являются лишь моим субъективным мнением.

useState имеет очевидное отличие от setState в компонентах класса, то есть useState не поверхностно объединяет состояния, в отличие от useReducer.

Чтобы проиллюстрировать это, вот пример использования useReducer для реализации «отменить/повторить»:

function init(initialState) {
  return {
    past: [],
    present: initialState,
    future: [],
  }
}
function reducer(state, action) {
  const { past, future, present } = state
  switch (action.type) {
    case 'UNDO':
      const previous = past[past.length - 1]
      const newPast = past.slice(0, past.length - 1)
      return {
        past: newPast,
        present: previous,
        future: [present, ...future],
      }
    case 'REDO':
      const next = future[0]
      const newFuture = future.slice(1)
      return {
        past: [...past, present],
        present: next,
        future: newFuture,
      }
    default:
      return state
  }
}

Добиться того же эффекта с помощью useState немного сложно, но не невозможно. Я просто хотел рассказать Ли, как легко использовать useReducer, что приводит ко второму пункту.

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

Легче понять другим разработчикам

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

Поскольку большинство фронтенд-разработчиков знакомы с Redux, использование useReducer может дать более быстрые преимущества, чем useState. Его основные концепции, такие как diapatch действия и использование редьюсера для обновления состояния, легче понять этим разработчикам, чем useState .

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

легче проверить

Самая обсуждаемая тема в Hooks RFC и Twitter — как тестировать хуки. Я думаю, что разработчикам потребуется некоторое время, чтобы понять лучшие практики тестирования хуков. Но если вы используете useReducer, то весь ваш код бизнес-логики, связанный с состоянием, можно поместить в одну функцию, отдельную от ваших компонентов, которую очень легко протестировать.

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

test('it supports undoing the state', () => {
  const state = { past: [{ count: 0 }], present: { count: 1 }, future: [] }
  const newState = reducer(state, { type: 'UNDO' })
  expect(newState.present.count).toBe(0)
})

Суммировать

Я не ожидаю, что люди будут использовать только useReducer, а не useState, и лично я тоже этого не делаю, у них есть свои варианты использования. Но я думаю, что useReducer лучше поддерживать, чем useState в сложных сценариях управления состоянием.