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

ОБНОВЛЕНИЕ 2018: Вышло второе издание (современный код и версии пакетов, данное издание УСТАРЕЛО)

На канале так же проводятся бесплатные вебинары, публикуются переводы и авторские материалы, присоединяйтесь!

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

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

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

Компонент (глупый)

Контейнер (умный)

Цель

Как это выглядит (разметка, стили)

Как это работает (получение данных, обновление состояния)

Осведомлен о Redux

Нет

Да

Для считывания данных

Читает данные из props

Подписан на Redux state (состояние)

Для изменения данных

Вызывает callback из props

Отправляет (dispatch) Redux действие (actions)

Пишутся

Вручную

Обычно, генерируются Redux

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

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

src/components/User.js

import React, { PropTypes, Component } from 'react'

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, { PropTypes, Component } from 'react'

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
}

Наш файл 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.

Last updated