Полное руководство по хуку useReducer() и управлению сложными состояниями.

В этом блоге мы подробно обсудим хук useReducer() в реакции. Мы поймем необходимость этого, когда его использовать и как его использовать.

Управление состоянием в реагирующем компоненте

Есть два хука для управления состоянием в реагирующем компоненте:

  1. useState и
  2. использованиередьюсер

Хук useState и его проблема

Если говорить об обработке состояния в функциональном компоненте react, то сразу приходит на ум хук useState(). Мы сохраняем данные с помощью хука useState(), ждем запуска какого-либо действия, и на основе этого действия данные состояния обновляются, и это запускает рендеринг компонента, через который новые изменения отражаются на веб-странице. Вот как работает хук useState().

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

Централизация данных компонентов с помощью хука useReducer()

Как обсуждалось выше, наличие нескольких useState в одном компоненте повлияет на качество кода. А что, если мы сосредоточим все данные компонентов в одном месте и будем управлять ими оттуда?

Звучит круто, верно?

Вы, наверное, уже догадались, что хук Yes useReducer() предназначен для централизации всех данных компонентов в одном месте и управления ими оттуда. Он похож на Redux, но его довольно легко реализовать, в отличие от Redux.

const INIT_STATE = {
    todo: [{id: 1, title: 'Go to gym'}]
}
function todoReducer(state, action) {}
const [state, dispatch] = useReducer(todoReducer, INIT_STATE);

Хук useReducer() принимает два аргумента:

  1. Исходное состояние. Исходное состояние (INIT_STATE) — это состояние компонента, который инициализируется некоторым значением.
  2. Функция редьюсера. Редьюсер — это чистая функция, которая принимает два параметра: текущее состояние и объект действия. В зависимости от объекта действия функция редуктора должна обновлять состояние неизменным образом и возвращать новое состояние.
function todoReducer(state, action) {
  switch (action.type) {
    case 'ADD_TODO':
      return {...state, todo: action.payload};
    default:
      return {...state};
  }
}

Затем хук useReducer() возвращает массив из двух элементов: текущее состояние и функцию отправки.

Функция отправки: функция отправки () используется всякий раз, когда вы хотите обновить состояние, точно так же, как вызов setState (). Вы просто вызываете функцию dispatch() и передаете соответствующий объект действия.

dispatch({
   type: 'ADD_TODO', 
   payload: [...state.todo, {id: 123, title: 'Learn React hooks'}]
});

Рабочий процесс хука useReducer()

Основываясь на определенных событиях или действиях, компонент вызывает функцию отправки, которая отправляет объект действия в функцию Reducer. Затем функция редуктора на основе типа действия возвращает новое состояние, которое отражается на веб-странице.

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

App.js

import './App.css';
import BetterMicroBlog from './BetterMicroBlog';

function App() {
  return (
    <div className="parent-component">
    <BetterMicroBlog />
    </div>
  );
}

export default App;

Лучший MicroBlog.js

import { useReducer, useRef } from "react";
import "./MicroBlog.css";

const BetterMicroBlog = () => {

    const postInput = useRef();

    const INIT_STATE = {
        data: [{id: Date.now(), content: "React is awesome 🔥"}],
        emptyMsg: false
    }

    function blogReducer(state, action) {
        switch(action.type) {
            case "ADD_POST":
                return {...state, data: action.payload, emptyMsg: false};
            case "DELETE_POST":
                return {...state, data: action.payload, emptyMsg: false};
            case "EMPTY_MSG":
                return {...state, emptyMsg: action.payload}
            default:
                return {...state};
        }
    }

    const [state, dispatch] = useReducer(blogReducer, INIT_STATE);
    
    function addPost() {
        const inputValue = postInput.current.value;
        if (inputValue !== "") {
            dispatch({
                type: "ADD_POST", 
                payload: [...state.data, {id: Date.now(), content: inputValue}]
            });
            postInput.current.value = "";
            return;
        }
        dispatch({
            type: "EMPTY_MSG",
            payload: true
        })
    }

    function deletePost(postId) {
        dispatch({
            type: "DELETE_POST", 
            payload: [...state.data.filter(post => post.id !== postId)]
        });
    }

    return (
    <div className="micro-blog">
    {
        state.emptyMsg ? 
        <div className="empty-msg">Please write something!</div>
        : null
    }
        <div className="micro-blog-head">
            <h2>What's happening?</h2>
            <input
             type="text" 
             className="blog-input"
             placeholder="Say Something!" 
             ref={postInput}
            />
            <button onClick={addPost} className="post-btn">
            Add Post
            </button>
        </div>
        <div>
        {
            state.data.map(post => (
                <div key={post.id} className="post-content">
                    <p>{post.content}</p>
                    <div>
                    <button
                     onClick={() => deletePost(post.id)} 
                     className="delete-btn">
                     Delete
                     </button>
                    </div>
                </div>
            ))
        }
        </div>
    </div>
  )
}

export default BetterMicroBlog;

Вывод

Спасибо, что дочитали до этого места. Надеюсь, теперь вы поняли хук useReducer() в React и его важность.

Если вы хотите больше такого контента, подписывайтесь на меня на Medium и на мой канал YouTube.

Какие-либо сомнения? связаться со мной в Твиттере.

Дополнительные материалы на PlainEnglish.io. Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Подпишитесь на нас в Twitter, LinkedIn, YouTube и Discord . Заинтересованы в хакинге роста? Ознакомьтесь с разделом Схема.