DevGang
Авторизоваться

Управление состоянием с помощью Unstated Next

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

В результате было опубликовано несколько библиотек управления состояниями для дальнейшего упрощения управления состояниями с помощью Context API, и в этой статье я расскажу о Unstated Next.

Что за Unstated Next?

Unstated Next - это библиотека, основанная на React Context API, которая позволяет глобально использовать состояние в наших приложениях. Unstated Next имеет простые методы API, которые можно использовать как методы Hooks или компонента. В последующих разделах я расскажу о методах API, а затем создам простую демонстрацию, чтобы продемонстрировать, как работает Unstated Next.

Unstated Next может быть установлен из Yarn или npm:

yarn add unstated-next 

// or

npm install unstated-next

Какие проблемы решает Unstated Next?

Поскольку Unstated Next построен на Context API, он решает те же проблемы, что и Context API. Unstated Next позволяет нам:

  1. Доступ к родительскому состоянию из дочерних компонентов
  2. Избегать сверления опор

Если вы не знакомы с Context API, желательно прочитать эту статью, прежде чем продолжить.

Unstated Next API методы

Unstated Next содержит три метода API, и я кратко расскажу о каждом из них:

createContainer(ourHook)

Метод createContainer используется для инициализации контекста и принимает в качестве аргумента Hook, состояние которого должно использоваться глобально. Этот контекст традиционно присваивается переменной, как показано ниже:  

import { createContainer } from 'unstated-next'

function ourHook() {}

let ourContext = createContainer(ourHook)
// ourContext == {Provider, useContainer}

Переменная, в свою очередь, возвращает провайдера и метод useContainer. Метод useContainer также может называться как потребитель.

Метод провайдера

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

import { createContainer } from 'unstated-next'

...

function Component() {}

<OurContainer>
  <Component />
</Ourcontainer>

<OurContainer initialState={"initial value"} />
  <Component />
</Ourcontainer>

useContainer(ctx)

Hook useContainer(ctx) принимает в качестве аргумента контекстную переменную и хранится в переменной, которая будет использоваться для доступа к глобальному состоянию. Hook useContainer(ctx) используется в компоненте, где состояние должны быть доступно - в этом случае дочерний компонент. Это будет продемонстрировано в следующем разделе.

import { useContainer } from "unstated-next"

function ChildComponent() {
  let activity = useContainer(OurContainer)
  return <input value={activity.value} onChange={activity.onChange} />
}

Выше представлены доступные методы API в библиотеках Unstated Next, которые построены исключительно на React API. В следующем разделе я буду создавать простое приложение, чтобы продемонстрировать, как работают методы.

Настройка

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

mkdir unstated-todo-app && cd unstated-todo-app
mkdir public src src/components
cd public && touch index.html style.css
cd ../src && touch index.js
cd components && touch Todos.js

Далее мы инициализируем каталог и установим необходимые зависимости.

npm init -y
npm i react react-dom react-scripts unstated-next

Теперь пришло время записать компонент рендеринга App в файл index.js.

index.js

Этот файл содержит компонент, отвечающий за рендеринг нашего компонента Todo``s. Сначала я импортирую необходимые зависимости:

import React from "react";
import { render } from "react-dom";
import TodoList from "./Components/Todos";

Не волнуйтесь, компонент TodoList будет построен после этого. Далее мы сообщаем React визуализировать наше приложение на узле div с идентификатором "root":  

function App() {
  return (
    <>
      <h3> Unstated Todo App </h3>
      <hr />
      <TodoList />
    </>
  )
}

render(<App />, document.getElementById("root"))

Далее мы начнем писать компонент Todo``s.

Todos.js

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

Мы начнем с создания нашего пользовательского хука и инициализации двумя объектами состояния:

import React, { useState } from "react";

function useTodos(initialstate = [{todo: "Test todo"}]) {
  let [todos, setTodo] = useState(initialstate)
  let [todo, setTodoItem] = useState("")

Наш Hook useTodos() принимает первоначальный список дел (который является необязательным), который отображается при загрузке приложения. У него два состояния объекта: todos и todo. Объект состояния todos - это массив всех задач в нашем приложении, в то время как объект состояния todo - это задача, добавляемая в массив todos и имеющая начальное значение пустой строки.

Значение todo устанавливается из пользовательского ввода, а затем добавляется в массив todos с помощью метода setTodo(), который мы рассмотрим далее.

...
  const handleInput = e => {
    setTodoItem(e.target.value)
  }

  const addTodo = e => {
    e.preventDefault()
    setTodo([...todos, {todo}])
    setTodoItem("")
  }

  const removeTodo = id => {
    const todoList = todos.filter(todo => todo.todo !== id)
    return setTodo(todoList)
  }

  return { todos, todo, addTodo, removeTodo, handleInput }

}
  1. Метод handleInput() используется для установки состояния todo к значению входов пользователя в форме, используя обработчик состояния setTodoItem.
  2. Метод addTodo() добавляет элемент to-do в массив todos с помощью метода setTodo([...todos, todo]). Затем он устанавливает состояние todo в пустую строку.
  3. Метод removeTodo() удаляет to-do из массива todos.

Затем мы возвращаем значения состояния и метода Хука, чтобы он был доступен в наших компонентах.

Далее мы создадим контейнер из нашего хука useTodo(). Во-первых, мы импортируем хук createContainer из Unstated. Далее:

// After the react import
import { createContainer } from "unstated-next";

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

let Todos = createContainer(useTodos)

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

function Todo({ todo }) {
  let todosContainer = Todos.useContainer()
  return (
    <>     
      <ul className="w3-ul w3-card-4">
        <li key={todo.todo} className="w3-display-container" >
           {todo.todo}
           <span className="w3-button w3-transparent w3-display-right" onClick={() => todosContainer.removeTodo(todo.todo)}>&times;</span>
        </li>
      </ul>
    </>
  )
}

Компонент выше отвечает за рендеринг todo переданного в качестве реквизита из итерации массива todos.

Далее мы создаем потребительский компонент, который отображает задачи и позволяет добавить задачу:

function DisplayTodos() {  
  let todosContainer = Todos.useContainer()
  return (
    <React.Fragment>
      <input type="text" className="w3-input w3-border w3-round" placeholder="Write an article" value={todosContainer.todo} onChange={todosContainer.handleInput} />
      <button onClick={todosContainer.addTodo} className="w3-button w3-round w3-black">Add Todo</button>
      <hr />
      {
        todosContainer.todos.map(todo => (
          <Todo todo={todo} />
        ))
      }
    </React.Fragment>
  )
}

В строках 8–12 мы перебираем состояние массива todos, а затем передаем каждый из них todo в качестве опоры компоненту Todo.

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

Далее мы определяем компонент, который отображает потребительский компонент DisplayTodos() под поставщиком контекста, так как ничто не может быть потреблено без поставщика.

export default function TodoList() {
  return (
    <Todos.Provider>
      <DisplayTodos />
    </Todos.Provider>
  )
}

Мы делаем компонент экспортом по умолчанию, так как он был импортирован для визуализации в компоненте App.

Запуск нашего приложения

С завершением процесса сборки нашего приложения, мы еще написать код для index.html и style.css файлов. Давайте сделаем это, прежде чем мы продолжим:

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
  <link rel="stylesheet" href="style.css" type="text/css">
  <title>Unstated-next Recipe App</title>
</head>
<body>
  <div id="root" class="w3-container"></div>
</body>
</html>

style.css

body {
  font-family: 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif;
  background-color: antiquewhite;
}

После этого давайте настроим package.json, чтобы мы могли запустить наше приложение. Под разделом scripts замените код там на:

"start": "react-scripts start"

Сделав это, давайте запустим приложение и посмотрим на него вживую http://localhost:3000:

npm run start

Вот демонстрация используемого приложения:

Вывод

Эта статья должна дать вам общее представление о том, что такое Unstated Next, его функциях и как оно работает. Основной вывод заключается в том, что вы можете использовать Unstated Next вместо традиционных React Context API Hooks и Redux.

Unstated Next - отличная библиотека React для управления приложениями состояния. Однако следует помнить, что существуют случаи, когда не следует использовать Context API и, следовательно, Unstated Next. Читайте о них в этой статье. Код, используемый в этой статье, можно найти на GitHub.

Источник:

#React
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

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

Попробовать

В этом месте могла бы быть ваша реклама

Разместить рекламу