Rematch: улучшенный обработчик состояния на основе Redux

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

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

В этой статье показан практический подход к использованию Rematch в качестве инструмента управления состоянием. Предварительное знание Rematch или Redux не требуется. Будут рассмотрены функции, архитектура и практическое использование Rematch. Вы узнаете об архитектуре Rematch при создании простого приложения с помощью React.

Что такое Рематч?

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

Это упрощает управление состоянием благодаря лучшему опыту разработчиков, используя принципы и функции Redux. Как и Redux, Rematch также с открытым исходным кодом.

Его можно легко интегрировать в проекты Reactjs, Vue.js, AngularJs и vanilla Javascript.

Он также предлагает практические функции, такие как поддержка React Devtools, поддержка TypeScript, побочные эффекты, плагины, создание нескольких магазинов и размер менее 2 КБ для улучшения опыта разработки. Полный список возможностей можно найти здесь.

Создание проекта с Rematch

Запустите приведенную ниже команду в своем терминале, чтобы создать проект React, установить все необходимые зависимости и посмотреть, все ли работает нормально:

npx create-react-app rematch-project
cd rematch-project
npm install @rematch/core react-redux @rematch/loading
npm start

Добавьте приведенный ниже блок кода в файл css:

body {
  padding: 2rem;
  margin: 0;
  background-color: #eee;
}
.container {
  display: flex;
  align-items: center;
  flex-direction: column;
}
.title {
  text-align: center;
  letter-spacing: 1px;
}
.card {
  box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.2);
  background-color: #fff;
  padding: 1rem;
  border-radius: 5px;
  margin: 1rem 0;
  width: 40%;
}
.card > h3 {
  text-transform: capitalize;
  color: #333;
}
.card > p {
  color: #888;
}

Теперь проект настроен; следующие разделы будут посвящены следующим функциям Rematch: магазин, модели и плагины.

1. Магазин

API Rematch предоставляет метод init, который инициализирует магазин Rematch (тайный магазин Redux с дополнительными функциями).

Создайте новый файл src/store.js и вставьте приведенный ниже код, чтобы инициализировать магазин:

import { init } from "@rematch/core";
const store = init({ 
  // config goes here
});
export default store;

Метод init получает объект config со следующими свойствами:

  • name: Название магазина, так как у вас может быть несколько магазинов.
  • models: Объект моделей; где каждая модель имеет состояние, редьюсер и эффекты.
  • plugins: набор плагинов; плагины — это конфигурации, расширяющие функциональность Rematch.
  • redux: объект, содержащий конфигурации Redux, такие как промежуточное ПО.

Чтобы подключить только что созданный store к приложению, замените код в src/index.js блоком кода ниже:

import ReactDOM from "react-dom/client";
import App from "./App";
import { Provider } from "react-redux";
import store from "./store";
import './index.css'
ReactDOM.createRoot(document.getElementById("root")).render(
  <Provider store={store}>
      <App />
  </Provider>
);

2. Модели

Модели — ключевая функция, которую Rematch использует для сокращения шаблонного кода; в рамках одной модели вы определяете начальные state, reducers и effects.

Это означает объединение типов действий, создателей действий, редукторов и состояния в одну объектную модель.

Вместо того, чтобы иметь все три отдельных, как в Redux, все они добавлены в одну модель, Javascript Object.

При этом кода меньше, но применяется та же логика Redux.

Чтобы добавить модель в наше приложение, создайте новый файл src/models.js и вставьте блок кода ниже, чтобы создать модель:

export const posts = {
    state: [],
    reducers: {
      loadedPosts: (state, payload) => payload,
    },
  };

Объект модели принимает следующие свойства:

  • state: Используется для определения начального состояния.
  • reducers: Объект чистых функций для изменения состояния модели.
  • effects: функция, используемая для обработки асинхронных действий.

Перейдите к src/store.js и добавьте модель.

import { posts } from "./models"
const store = init({
  models: { posts },
})

Если вы проверите с помощью инструментов разработки Redux, вы увидите, что начальное состояние модели было добавлено в хранилище.

Нам также нужно будет добавить Side Effects: функции с доступом к состоянию своей модели и редьюсерам; effects используются для обработки асинхронных действий.

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

Для обработки этого действия будет создан effect.

Обновите src/models.js блоком кода ниже:

export const posts = {
  state: [],
  reducers: {
    loadedPosts: (state, payload) => payload,
  },
  effects: (dispatch) => ({
    async load() {
      const data = await loadPosts();
      dispatch.posts.loadedPosts(data);
    },
  }),
};
const loadPosts = async () => {
  const posts = await fetch("https://jsonplaceholder.typicode.com/posts");
  const data = await posts.json();
  return data;
};

Асинхронная функция loadPosts извлекает данные.

Внутри объекта model создается effect. Он вызывает loadPosts и добавляет возвращаемое значение в редюсер loadedPosts как payload.

3. Плагины

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

Некоторые из доступных плагинов:

Давайте реализуем плагин загрузки.

Обновите src/store.js, реализовав файл loadingPlugin.

import loadingPlugin from "@rematch/loading"
const store = init({
  models: { posts },
  plugins: [loadingPlugin()], // Add loading plugin
})

Этот плагин определяет, когда запускается effect, и устанавливает loading в true. Когда наш компонент будет собран, подключаемый модуль загрузки будет реализован для определения, когда loading равно true в компоненте.

Повтор сеанса с открытым исходным кодом

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

Начните получать удовольствие от отладки — начните использовать OpenReplay бесплатно.

Создание компонента

Теперь, когда Rematch настроен, давайте приступим к созданию компонента приложения.

Обновите src/App.js с помощью приведенного ниже блока кода:

import { connect } from "react-redux";
function App({ posts, loading }) {
  console.log(posts, loading)
  return (
    <div className="container">
      {loading ? (
        <h1>Loading...</h1>
      ) : (
        <>
          <h1 className="title">Posts</h1>
            {posts.map((post, index) => (
              <div className="card" key={index}>
                <h3>{post.title.slice(0, 20)} </h3>
                <p>{post.body}</p>
              </div>
            ))}
        </>
      )}
    </div>
  );
}
const mapState = (state) => ({
  posts: state.posts,
  loading: state.loading.models.posts,
});
const mapDispatch = (dispatch) => ({
  load: dispatch.posts.load(),
});
export default connect(mapState, mapDispatch)(App);

Некоторые пояснения:

  • Метод connect связывает компонент App с хранилищем, предоставляя ему доступ к state и dispatch хранилища.
export default connect(mapState, mapDispatch)(App);
//  mapState and mapDispatch functions are passed as the first two parameters within connect
  • mapState получает состояние хранилища и будет вызываться при каждом изменении состояния хранилища.
  • mapDispatch получит dispatch вашего магазина, предоставив вашему компоненту доступ к магазинам reducers и effects. Эффект load является асинхронным, поэтому при срабатывании loading автоматически устанавливается на true.
  • Внутри компонента состояние и действия легко деструктурируются как props.
function App({ posts, loading }) {
  //
}

Заключение

Матч-реванш не только прямолинеен, чист и прост; его функциональность может быть расширена через его плагин API.

Начать работу с Rematch очень просто, и вы получите потрясающий опыт разработчика, независимо от того, являетесь ли вы новичком в управлении состоянием или опытным пользователем Redux.

Рассмотрите возможность использования Rematch в качестве инструмента управления состоянием для вашего следующего проекта и поделитесь своим опытом в разделе комментариев ;)

Ресурсы

Чтобы узнать больше о react-redux connect(), посетите документы.

Посетите Живые ссылки и Исходный код этого проекта.

Больше примеров проектов Rematch можно найти здесь для дальнейшей практики.

СОВЕТ ОТ РЕДАКТОРА. Чтобы получить еще один взгляд на Rematch, взгляните на нашу статью Rematch — лучший Redux? статью — и если вы хотите рассмотреть другие варианты, не пропустите Zustand: простое современное управление состоянием для React и Управление состоянием в React с MobX!

Первоначально опубликовано на https://blog.openreplay.com 1 сентября 2022 г.