Контейнеры и компоненты

Прежде чем мы разобьем App.js на компоненты User.js и Page.js хотелось бы отметить про разделение на «компоненты» и «контейнеры», иначе называемые: «глупые» и «умные» компоненты, «Presentational» and «Container» Components и быть может как-то еще.

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

Компонент (глупый) Контейнер (умный)
Цель Как это выглядит (разметка, стили) Как это работает (получение данных, обновление состояния)
Осведомлен о Redux Нет Да
Для считывания данных Читает данные из props Подписан на Redux state (состояние)
Для изменения данных Вызывает callback из props Отправляет (dispatch) Redux действие (actions)
Пишутся Вручную Обычно, генерируются Redux

Магия таблиц обычно проявляется не сразу. Если переписать наше приложение, а потом взглянуть сюда еще раз — многое станет гораздо яснее. Давайте так и поступим. Поехали!

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

src/components/User.js

import React, { Component } from 'react'
import PropTypes from 'prop-types'

export default class User extends Component {
  render() {
    const { name } = this.props
    return <div>
      <p>Привет, {name}!</p>
    </div>
  }
}

User.propTypes = {
  name: PropTypes.string.isRequired
}

src/components/Page.js

import React, { Component } from 'react'
import PropTypes from 'prop-types'

export default class Page extends Component {
  render() {
    const { year, photos } = this.props
    return <div>
      <p>У тебя {photos.length} фото за {year} год</p>
    </div>
  }
}

Page.propTypes = {
  year: PropTypes.number.isRequired,
  photos: PropTypes.array.isRequired
}

Теперь доступ к PropTypes через основной пакет React отсутствует (удален в React начиная с версии 16.0). Импортировать его можно из отдельного пакета prop-types версии 15 (на данный момент актуальная версия 15.6.1) из npm. Так как его требуют такие пакеты, как es-lint-plugin-react, react, react-hot-loader, react-redux, то он уже установился при их установке. Для получения информации по использованию, совместимости, миграции и т.д., см. https://fb.me/prop-types-docs.

Наш файл App.js уже практически и есть container, он даже лежит в соответствующей папке. Изменим-с...

src/containers/App.js

import React, { Component } from 'react'
import { connect } from 'react-redux'
import User from '../components/User'
import Page from '../components/Page'

class App extends Component {
  render() {
    const { user, page } = this.props
    return <div>
      <User name={user.name} />
      <Page photos={page.photos} year={page.year} />
    </div>
  }
}

function mapStateToProps (state) {
  return {
    user: state.user,
    page: state.page
  }
}

export default connect(mapStateToProps)(App)

Теперь можно обновлять компоненты Page и User независимо друг от друга. Чем мы и займемся в следующей главе, изучая actions.

results matching ""

    No results matching ""