Сокращение шаблонов состояний и диспетчеризации React-Redux

Обычно я создаю свои компоненты, используя следующий шаблон:

import selectors from '../store/selectors'
import someAction1 from '../actions/someAction1'
import someAction2 from '../actions/someAction2'
import someAction3 from '../actions/someAction3'

class MyComponent extends React.Component {
  render() => {
    return <Fragment>
      <div>{this.props.someReduxProperty1}</div>
      <div>{this.props.someReduxProperty2}</div>
      <div>{this.props.someReduxProperty3}</div>
      <a onClick={this.props.someAction1}>Action1</a>
      <a onClick={this.props.someAction2}>Action2</a>
      <a onClick={this.props.someAction3}>Action3</a> 
    </Fragment>
  }
}

export default connect(
  (state, ownProps) => {
    return {
      someReduxProperty1: selectors.getSomeReduxProperty1(state),
      someReduxProperty2: selectors.getSomeReduxProperty2(state),
      someReduxProperty3: selectors.getSomeReduxProperty3(state)
    }
  },
  (dispatch) => {
    return {
      someAction1: () => {
        dispatch(someAction1())
      },
      someAction2: () => {
        dispatch(someAction2())
      },
      someAction3: () => {
        dispatch(someAction3())
      }
    }
  }
)(MyComponent)

Это выполняет свою работу, но кажется, что я постоянно печатаю одни и те же вещи, даже в этом тривиально коротком примере. Компоненты моего контейнера кажутся довольно многословными к тому времени, когда они функционируют. Кроме того, я обнаружил, что часто изменяю список свойств и действий, используемых в компоненте, что немного утомляет постоянный ввод всего этого заново. Однако большинство примеров, которые я читал о react + redux, похоже, отражают эту настройку кода.

Это действительно необходимо? Я подумываю игнорировать то, что кажется лучшими практиками React + Redux, и просто передавать state и dispatch в качестве реквизита для моих компонентов:

import selectors from '../store/selectors'
import someAction1 from '../actions/someAction1'
import someAction2 from '../actions/someAction2'
import someAction3 from '../actions/someAction3'

class MyComponent extends React.Component {
  render() => {
    const { state, dispatch } = this.props
    return <Fragment>
      <div>{selectors.getSomeReduxProperty1(state)}</div>
      <div>{selectors.getSomeReduxProperty2(state)}</div>
      <div>{selectors.getSomeReduxProperty3(state)}</div>
      <a onClick={() => { dispatch(someAction1()) }}>Action1</a>
      <a onClick={() => { dispatch(someAction2()) }}>Action2</a>
      <a onClick={() => { dispatch(someAction3()) }}>Action3</a>
    </Fragment>
  }
}

export default connect(
  (state, ownProps) => {
    return { state: state }
  }
  /* dispatch gets added by default */
)(MyComponent)

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

export default connectHelper = (componentClass) => {
  return connect((state) => {
    return { state: state }
  })(componentClass)
}
class MyComponent extends React.Component {
  ...
}

export default connectHelper(MyComponent)

Я теряю возможность сразу увидеть, какие свойства используются в моем магазине Redux, просто пропустив вызов connect. Я в порядке с этим.

Итак, мой вопрос (ы):

  1. Есть ли какие-либо другие соображения, которыми я бы пожертвовал, по существу, в обход mapStatetoProps? Меня беспокоит то, что, поскольку существует только одно свойство state, React может чрезмерно усердно перерисовывать каждый компонент каждый раз, когда изменяется какое-либо свойство в хранилище Redux. Поэтому необходимо сопоставлять свойства вручную в mapStateToProps?

  2. Что я теряю, пропуская mapDispatchToProps и используя введенный по умолчанию this.props.dispatch? Мне нужно выполнить «дополнительную» работу, чтобы отобразить состояния непосредственно в mapDispatchToProps; что я получу за эти усилия?

  3. Существуют ли другие организации/шаблоны кода, которые помогают уменьшить беспорядок свойств компонентов в настройке React+Redux?

Спасибо! Просто голова кружится вокруг этих инструментов. Это было веселое упражнение, но некоторые вещи казались немного причудливыми!


person BU0    schedule 16.01.2019    source источник


Ответы (1)


Да, есть много способов сократить это.

Во-первых, вы должны использовать сокращенная форма объекта mapDispatch:

const mapDispatch = {
    someAction1,
    someAction2,
    someAction3,
};

Во-вторых, хотя у нас нет эквивалента «сокращения объекта» для mapState, вы можете использовать Reselect createStructuredSelectorAPI, чтобы делать то же самое.

И да, если вы передадите все значение state, ваш компонент теперь будет перерисовываться для каждого обновления в магазине Redux. React-Redux выполняет много работы внутренне, чтобы убедиться, что ваш собственный компонент выполняет повторный рендеринг только при необходимости, и это основано на значениях, возвращаемых вашей функцией mapState.

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

Наконец, хотя это и не относится к React, ознакомьтесь с нашим новым пакетом redux-starter-kit. Он включает в себя утилиты для упрощения нескольких распространенных вариантов использования Redux, включая настройку хранилища, определение редьюсеров, неизменяемую логику обновления, проверку случайных мутаций и даже автоматическое создание целых «фрагментов» состояния без написания каких-либо типов действий или создателей действий вручную.

person markerikson    schedule 16.01.2019
comment
Вау, спасибо, Марк! Много информации в этих ссылках, спасибо за их публикацию! Это супер полезно! - person BU0; 16.01.2019
comment
Конечно. Вас также могут заинтересовать некоторые другие сообщения из моей серии Idiomatic Redux, как а также мои слайды семинара по основам Redux. - person markerikson; 16.01.2019