Как управлять сложным состоянием пользовательского интерфейса с помощью хука useReducer вместо редукса

Если вы тот, кто использует самую популярную библиотеку внешнего интерфейса Реагировать для создания своего пользовательского интерфейса вы наверняка слышали о свойствах и состоянии, которые запускают обновление пользовательского интерфейса при изменении любого из них; государство может быть местным
состояние (синхронное) или состояние сети (асинхронное).

Управление состоянием в React всегда было предметом разговоров с таким количеством библиотек, таких как: redux, mobx, recoilи этот список можно продолжить, позвольте мне объяснить вам, как мы можем использовать это без добавления каких-либо дополнительных зависимостей к приложению и уменьшения размера пакета приложения.

Если вы уже давно пользуетесь React (по крайней мере, с React 16.3), возможно, вы слышали об одной из самых популярных библиотек Редукс для управления сложным состоянием пользовательского интерфейса из-за его предсказуемого состояния и поддержки асинхронного управления состоянием с помощью редукционный преобразователь а также редукс-сага библиотеки.

Существует множество библиотек, которые вы можете использовать в качестве промежуточного программного обеспечения в избыточности и расширить возможности избыточности. Если вы настраиваете редукс с нуля, вам необходимо настроить шаблонный код, прежде чем вы начнете над ним работать. Последние версии Redux предлагают API на основе хуков, чтобы уменьшить некоторые шаблоны, но все же вам нужно знать о действия, редукторы, промежуточное ПОи так далее.

Если вы используете последнюю версию React или React 16.8 или выше, возможно, вы уже используете одну из самых популярных функций, представленных в React: крючки. Хуки помогают вам писать компоненты без написания классов и с легкостью управлять состоянием реагирующего приложения.

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

Предположим, что мы создаем простое приложение CRUD для библиотеки книг, в котором вы можете добавлять, удалять и управлять своей библиотекой в ​​зависимости от ваших интересов. Я использую один из шаблонов пользовательского интерфейса React, широко используемых с избыточностью, шаблон контейнера и презентационных компонентов чтобы продемонстрировать этот пример, он может соответствовать любому шаблону, который вы уже используете.

books-container.js

import React, {useReducer, useMemo, useEffect, useRef} from 'react'
import _ from 'lodash'
import BooksLayout from './books-layout'



const bindActionCreators = (reducerMap, dispatch) =>
  _.reduce(
    reducerMap,
    (result, val, type) => ({
      ...result,
      [type]: payload => dispatch({type, payload}),
    }),
    {}
  )


const initialState = {
  books: {}, 
  
  
  bookReadState: null
  bookDeleteState: null
  bookUpdateState: null
}

const reducerMap = {
  setBooks: (state, books) => ({
    ...state,
    books,
  }),
  updateBook: (state, book) => ({
    ...state,
    books: 
  },
  deleteBook: (state, book) => ({
    ...state,
    books: 
  }),
  setBookReadState: (state, bookReadState) => ({
    ...state, bookReadState
  }),
  setBookUpdateState: (state, bookUpdateState) => ({
    ...state, bookUpdateState
  }),
  setBookDeleteState: (state, bookDeleteState) => ({
    ...state, bookDeleteState
  }),
}

const useService = ({id, actions}) => {
  
  
  
  const abortController = useRef(new global.AbortController())

  actions = useMemo(
    () => ({
      ...actions,
      readBooks: async () => {
        try {
          const data = await readBooks({
            fetchCallback: actions.setBookReadState})
          actions.setBooks(data)
        } catch(error) {
          
        }
      },
      updateBook: async book => {
        try { 
          const data = await updateBook({book, 
            fetchCallback: actions.setBookUpdateState})
          actions.updateBook(data)
        } catch(error) {
          
        }
      },
      deleteBook: async id => {
        try {
          const data = await deleteBook({id, 
            fetchCallback: actions.setDeleteReadState})
          actions.deleteBook(data)
        } catch {
          
        }
      },
    }),
    [actions]
  )

  useEffect(() => {
    const controller = abortController.current
    
    
    actions.readBooks()
    
    return () => {
      controller.current.abort()
    }
  }, [actions])

  return {actions}
}

const reducer = (state, {type, payload}) => reducerMap[type](state, payload)

const BooksContainer = props => {
  const [state, dispatch] = useReducer(reducer, initialState)
  const actions = useMemo(() => bindActionCreators(reducerMap, dispatch), [])
  const service = useService({...props, state, actions})

  return (
    <BooksLayout
      {...state}
      {...service}
      {...props}
    />
  )
}

export default BooksContainer

books-layout.js

import React from 'react'

const BooksLayout = ({books, actions, bookReadState, ...props}) => {
  return (
    <>
    {bookReadState === 'loading' ? <div>Loading...</div> : 
      {books.map(book => (
          // UI Logic to display an each book
          // button to click to delete 
          // call actions.deleteBook(id)
          )
        )
      }
    }
    </>
}

export default BooksLayout

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

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

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

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

Похожие записи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *