избыточное исследование: матч-реванш

внешний интерфейс Командная строка React.js Redux

Проблемы с редуксом

  • Шаблонные файлы redux в проекте слишком разбросаны, и их сложно писать и поддерживать.

  • Использование преобразователей для обработки асинхронных операций не так интуитивно понятно.

Сравнение схем

Схема управления на основе редукционного потока данных:Dva,mirrorа такжеrematch

Dva

Dva — это решение для управления потоками данных с открытым исходным кодом от Ant Financial, основанное на redux и redux-saga, которое упрощает процесс разработки. Dva – это пакетное решение. Вы можете использовать очень навязчивый dva-cli для быстрой сборки проектов и обеспечения адаптации на уровне маршрутизации; вы также можете использовать dva-core для введения кода ядра, чтобы уменьшить навязчивость.

недостаток
  • Существующие проекты будут иметь серьезные изменения, если они будут использовать весь набор фреймворков Dva.

  • Dva использует redux-saga для обработки асинхронности, а стоимость обучения относительно высока.

mirror

Редукционная схема потока данных похожа на Два, последнее обновление два месяца назад, релиза версии 1.0 не было

rematch

rematch был вдохновлен Dva и Mirror, он сочетает в себе немного того и другого.

преимущество
  • Использование файловой структуры модели, аналогичной Dva, унифицированное управление синхронными и асинхронными операциями.

  • Метод async/await реализуется через промежуточный ключ для обработки асинхронности, а сага о редукции в Dva заброшена.

  • Предусмотрены элементы конфигурации Redux, совместимые со старым кодом в проекте.

  • Поддержка нескольких магазинов

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


Rematch Mirror Dva
Применимая структура Все кадры/без кадров React React
Применимый маршрут все маршруты / нет маршрутов RR4 RR3, RR4 / не использовать маршрутизацию
мобильный ×
инструменты разработчика Redux, Reactotron Redux Redux
плагин
reducers
effects async/await async/await redux saga
effect params (payload, internals) (action, state) (action, state)
Метод мониторинга subscriptions hooks subscriptions
Ленивая загрузка моделей
прикованная отправка
отправить напрямую
dispatch promises
Загрузить плагин
persist plugin
package size 14,9 КБ (сжато: 5,1 КБ) || избыточность + преобразователь: 6 КБ (2 КБ) 130,4 КБ (в сжатом виде: 33,8 КБ) два ядра: 72,6 КБ (в сжатом виде: 22,5 КБ)

rematch

API

  import { init } from '@rematch/core';
  ​
  const store = init({
    models: {
      count: {
        state: 0,
        reducers: {
          add: (state, payload) => state + payload,
          del: (state, payload) => state - payload,
          'otherModel/actionName': (state, payload) => state + payload,
        },
        effets: {
          async loadData(payload, rootState) {
            const response = await fetch('http://example.com/data')
            const data = await response.json()
            this.add(data)
          }
        }
      }
      list: {}
    },
    redux: {
      reducers: {},
      middlewares: [thunk],
    },
    plugins: [loading]
  })

init

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

models: { [string]: model }

Объект с ключом свойства в качестве ключа в rootState

model.state: any

используется для инициализации модели

model.reducers: { [string]: (state, payload) => any }

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

model.effects: { [string]: (payload, rootState) }

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

redux

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

plugins

rematch — это система плагинов, с помощью которой можно настроить сторонние плагины.

редукционный процесс:


Процесс реванша:

пример

  ##index.js
  import React from 'react'
  import ReactDOM from 'react-dom'
  import { Provider } from 'react-redux'
  import { init } from '@rematch/core'
  import App from './App'
  ​
  const count = {
    state: 0,
    reducers: {
      increment: s => s + 1,
    },
    effects: dispatch => ({
      async asyncIncrement() {
        await new Promise(resolve => {
          setTimeout(resolve, 1000)
        })
        dispatch.count.increment()
      },
    }),
  }
  ​
  const store = init({
    count,
  })
  ​
  // Use react-redux's <Provider /> and pass it the store.
  ReactDOM.render(
    <Provider store={store}>
      <App />
    </Provider>,
    document.getElementById('root')
  )
  ​
  ​
  ##App.js
  import React from 'react'
  import { connect } from 'react-redux'
  ​
  // Make a presentational component.
  // It knows nothing about redux or rematch.
  const App = ({ count, asyncIncrement, increment }) => (
    <div>
      <h2>
        count is <b style={{ backgroundColor: '#ccc' }}>{count}</b>
      </h2>
  ​
      <h2>
        <button onClick={increment}>Increment count</button>{' '}
        <em style={{ backgroundColor: 'yellow' }}>(normal dispatch)</em>
      </h2>
  ​
      <h2>
        <button onClick={asyncIncrement}>
          Increment count (delayed 1 second)
        </button>{' '}
        <em style={{ backgroundColor: 'yellow' }}>(an async effect!!!)</em>
      </h2>
    </div>
  )
  ​
  const mapState = state => ({
    count: state.count,
  })
  ​
  const mapDispatch = dispatch => ({
    increment: dispatch.count.increment,
    asyncIncrement: dispatch.count.asyncIncrement,
  })
  ​
  // Use react-redux's connect
  export default connect(
    mapState,
    mapDispatch
  )(App)
  ​

Доступ к старым проектам

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

1. Установите зависимости и удалите избыточность в зависимостях

yarn add @rematch/core

пряжа удалить избыточность (удаление избыточности может привести к тому, что eslint сообщит об ошибках)

2. Измените файл записи редукции

  src/store/index.js
  ​
  import { init } from '@rematch/core';
  import thunk from 'redux-thunk';
  import reduxReducerConfig from '@/reducers';
  import models from '../models';
  ​
  const store = init({
    models,
    redux: {
      reducers: {
        ...reduxReducerConfig
      },
      middlewares: [thunk],
    },
  });
  ​
  export default store;

3. Измените входной файл редукторов

  import { routerReducer as routing } from 'react-router-redux';
  - import { combineReducers } from 'redux';
  import dispatchConfigReducer from './dispatch-config';
  import counterReducer from './count';
  ​
  - export default combineReducers({
  -   routing,
  -   dispatchConfigReducer,
  -   counterReducer,
  - });
  ​
  + export default {
  +   routing,
  +   dispatchConfigReducer,
  +   counterReducer,
  + };

4. Добавьте входной файл модели

  + src/models
  + src/models/re-count.js
  + src/models/config-list.js
  + src/models/index.js
  ​
  index.js
  ​
  import reCount from './re-count';
  import configList from './config-list';
  ​
  export default {
    reCount,
    configList,
  };

Если в старом проекте не используется избыточность, вы можете использоватьyarn remove thunkУдалите папку зависимостей и редукторов thunk, и вам не нужно передавать конфигурацию redux при инициализации init.

Если вы получаете доступ к рематчу, вам нужно заблокировать версию.Редукционная версия, представленная в рематче, - 4.0.0, поэтому редукс в старом проекте должен быть обновлен до 4.0.0, иначе при упаковке будут введены обе версии редукции.

Новая конфигурация проекта

  index.js
  ​
  import React from 'react';
  import { render } from 'react-dom';
  import { browserHistory, Router } from 'react-router';
  import { syncHistoryWithStore } from 'react-router-redux';
  import { Provider } from 'react-redux';
  import routes from '@/routes';
  import store from '@/store';
  import '@/styles/index.less';
  ​
  const history = syncHistoryWithStore(browserHistory, store);
  ​
  render(
    <Provider store={store}>
      <Router history={history} routes={routes} />
    </Provider>,
    document.getElementById('root'),
  );
  ​
  ---------------------------------------------------------------------------------------
  ​
  新建store文件夹,并添加index.js
  ​
  import { init } from '@rematch/core';
  import { routerReducer as routing } from 'react-router-redux';
  import models from '../models';
  ​
  const store = init({
    models,
    redux: {
      reducers: {
        routing,
      },
    },
  });
  ​
  export default store;
  ​
  ---------------------------------------------------------------------------------------
  ​
  新建models文件夹,并添加index
  ​
  models结构
  ├── common
  │   ├── bizLineList.js
  │   └── index.js
  └── index.js

bug

Redux DevTools необходимо обновить до последней версии, в версии 2.16.0 есть ошибки

Ссылаться на

Переосмыслить Редукс

Rematch: редизайн Redux

Интенсивное чтение «Переосмысление Redux»