Хуки React были представлены в версии 16.8, а useReducer — это один из дополнительных хуков, которые поставлялись вместе.

Зачем использовать useReducer?

Это альтернатива хуку useState для управления состоянием, но поток обновления состояния в обоих хуках совершенно разный.

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

Чтобы решить вышеуказанные проблемы, react предоставила хук useReducer. Хук делает это, извлекая управление состоянием из компонента.

Как использовать useReducer?

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

const [state, dispatch] = useReducer(reducer, initialState, init);

Исходное состояние: это значение, с которым инициализируется состояние.

reducer: это чистая функция, которая принимает два параметра: текущее состояние и объект действия, и на основе действия изменяет состояние и возвращает измененное состояние.

init: это функция, используемая для ленивого создания начального состояния.

отправка: принимает объект действия и отправляет его функции редуктора.

Как работает useReducer Hook?

Хук useReducer следует архитектуре одностороннего потока, аналогичной архитектуре Flux, для обновления состояния с помощью действий.

Функция отправки используется различными прослушивателями событий для отправки действий. Объект действия содержит два значения: одно — это тип («то есть тип действия, которое должно быть выполнено»), а второй параметр («необязательный») — полезная нагрузка («данные/значение»), эта диспетчерская функция вызывает редюсер и передает ей текущее состояние и объект действия.

Функция редьюсера в соответствии с переданным действием соответственно обновляет состояние и возвращает обновленное состояние, в результате компонент перерисовывается. useReducer возвращает обновленное состояние.

Реализация счетчика

Задача — реализовать встречное приложение. В приложении есть две кнопки: одна для увеличения счетчика, а другая для уменьшения счетчика и вывода для отображения текущего счетчика.

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

const initialState = { count : 0 };

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

const reducer = (state, action) => {
    switch(action.type){
        case 'INCREMENT':
           return {...state, count: state.count + 1};
        case 'DECREMENT':
           return {...state, count: state.count - 1};
        default:
           return state;
    }
}

Наконец, нам нужно объявить useReducer(), создать объект действия увеличения и уменьшения и связать функцию отправки с прослушивателем событий onClick() с их объектом действия.

const Counter = () => {
    const [state, dispatch] = useReducer(reducer, initialState);
   
    incrementAction = { type: 'INCREMENT' };
    decrementAction = { type: 'DECREMENT' };
    
    return (
       <div>
          <button onClick={() => dispatch(incrementAction)}>
             Increase Count
          </button>
          
          <span>
             {state.count}
          </span>
          
          <button onClick={() => dispatch(decrementAction)}>
             Decrease Count
          </button>
       <div>
    )
}

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

Код — https://github.com/akshaybarya/Counter-app-using-useReducer

Реализация регистрационной формы

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

Структура состояния будет представлять собой объект с ключами name, email, password и tnc с начальными значениями в виде пустой строки и значением tnc в виде false.

const initialState = { 
    name: '',
    email: '',
    password: '', 
    tnc: false
};

Функция редуктора имеет оператор switch с тремя случаями: один для обновления состояния, другой для переключения условий и положений и случай по умолчанию.

const reducer = (state, action) => {
    
    switch(action.type) {
        case 'HANDLE INPUT TEXT': 
          return { 
            ...state,
            [ action.field ] : action.payload
          }; 
        case 'TOGGLE TNC': 
          return { 
            ...state,
            tnc: !state.tnc
          }; 
        default: 
          return state;
    }
}

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

const RegistrationForm = () => {
    const [ state, dispatch ] = useReducer(reducer, initialState);
  
    const handleTextChange = (e) => {
        dispatch({
           type : 'HANDLE INPUT TEXT',
           field : e.target.name,
           payload : e.target.value 
        });
    }
  
    return (
        <form>
           <label>
              Enter Name:
 
              <input type='text'
               name='name'
               placeholder='Enter Name' 
               value={state.name} 
               onChange={handleTextChange} 
              />
           </label>
         
           <label>
              Enter Email:
 
              <input type='email'
               name='email' 
               placeholder='Enter Email'
               value={state.email} 
               onChange={handleTextChange} 
              />
           </label> 
         
           <label>
              Enter Password:
 
              <input type='password'
               name='password'
               placeholder='Enter Password' 
               value={state.password} 
               onChange={handleTextChange} 
              />
           </label>
         
           <label>
               Terms & Conditions:
 
               <input type='checkbox'
                name='tnc' 
                aria-label='Terms & Condition'
                checked={state.tnc}
                onChange={() => dispatch({ type: 'TOGGLE TNC' })}
               />
           </label>
   
           <input type="submit" value="Submit"> 
        </form>       
    ) 
}

Код — https://github.com/akshaybarya/Registration-Form-using-useReducer

Когда использовать хук useReducer

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

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

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

Хук useState предпочтительнее для простого управления состоянием, а хук useReducer — для сложного управления состоянием.

Заключение

Хук useReducer помогает нам отделить логику управления состоянием от логики рендеринга в компоненте.

Ловушка принимает три параметра, функцию редуктора, начальное состояние и функцию инициализации, а также возвращает массив, содержащий текущее состояние компонента и функцию отправки.

Для обновления состояния используется функция диспетчеризации с соответствующим объектом действия. Объект действия пересылается функции редуктора с текущим состоянием компонента, функция редуктора обновляет состояние. Если функция редьюсера обновляет состояние, компонент выполняет повторную визуализацию, и useReducer возвращает обновленное состояние.

Если вам понравилась эта история, нажмите кнопку 👏 и поделитесь ею, чтобы другие тоже могли ее найти! Кроме того, не стесняйтесь оставлять комментарии ниже.

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

Мы набираем сотрудников. Посмотреть вакансии здесь.