Должен ли я использовать ComponentDidMount или mergeProps функции подключения для извлечения данных? - PullRequest
0 голосов
/ 19 февраля 2019

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

const ConnectedComponent = connect(
  state => ({
    dataSet: state.dataSet
  }),
  dispatch => ({
    loadData: () => {
      ...
      fetch data and dispatch it to the store
      ...
    }
  })
)(MyComponent); 

class MyComponent extends Component {
  ...
  componentDidMount() {
    const { dataSet, loadData } = this.props;
    if (!dataSet) {
      loadData();
    }
  } 
  ... 
  render () {
    const { dataSet } = this.props;
    if (dataSet) {
      // render grid with data
    } else {
      // render Loading...
    }
  }
}

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

const ConnectedComponent = connect(
  state => ({
    dataSet: state.dataSet
  }),
  dispatch => ({ 
    dispatch 
  }),
  (stateProps, dispatchProps) => {
    const { dataSet } = stateProps;
    const { dispatch } = dispatchProps;

    if (!dataSet) {
      // fetch data asynchronously and dispatch it to the store
    } 

    return {
      ...stateProps
    };
  }
)(MyComponent); 

class MyComponent extends Component {
  render () {
    const { dataSet } = this.props;
    if (dataSet) {
      // render grid with data
    } else {
      // render Loading...
    }
  }
}

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

Есть ли недостатки такого подхода?

PS: я использую redux-thunk для асинхронной выборки.

1 Ответ

0 голосов
/ 19 февраля 2019

Второй подход, как разделение понятий , потенциально является хорошим решением из-за уровней и разделения ответственности - ConnectedComponent отвечает за выборку данных, тогда как MyComponent действует как компонент представления.Хорошо!

Но диспетчеризация действий в connect mergeProps не кажется хорошей идеей, потому что вы вводите побочные эффекты .

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

  1. Подключенные компоненты вызывают API для необходимых сущностей.
  2. При извлечении сущностей мы показываем загрузчик.
  3. Когда данные доступны, мы передаем их компонентам Presentational.

Из-за вышеуказанных недостатков я могу предложить вам организовать и повторно использовать поток выборки данных в HOC .

Вот псевдокод и поток (взятый из моей статьи), который устраняет вышеуказанные недостатки:

* Я использовал его в течение последнего года ипродолжайте придерживаться его.

Сборщик HOC:

import authorActions from 'actions/author'

const actions = {
  'Author': authorActions
}

export default (WrappedComponent, entities) => {

  class Fetcher extends React.Component {
    // #1. Calls the API for the needed Entities.
    componentDidMount () {
      this.fetch()
    }

    fetch () {
      const { dispatch } = this.props

      entities.forEach(name => dispatch(actions[name].get()))
    }

    render () {
      const { isFetching } = this.props

      // #2. While fetching the Entities, we're showing an Loader.
      if (isFetching) return <Loader />

      return <WrappedComponent {...this.props} />
    }
  }

  const mapStateToProps = state => {
    const isFetching =  entities
      .map(entity => state[entity].isFetching)
      .filter(isFetching => isFetching)

    return { isFetching: isFetching.length > 0 }
  }

  return connect(mapStateToProps)(Fetcher)
}

Использование:

const MyComponent = ({ authors }) => <AuthorsList authors={authors} />

const mapStateToProps = state => ({
  authors: state.authors
})

const Component = connect(mapStateToProps)(MyComponent)
export default Fetcher(Component, ['Author'])

ЗдесьВы можете прочитать статью и углубиться в ее идеи и концепции:

* Концепция сборщика адресована на Занятие № 2: Контейнеры на стероидах

Долгосрочная React & Redux SPA - Извлеченные уроки

...