- PVSM.RU - https://www.pvsm.ru -

Функциональные компоненты

Как говорится, в редакцию пришло письмо: "не могли бы вы подробно разъяснить..." Отвечаю публично, кому оно надо, а применение можно пощупать тут [1].

Сначала были компоненты на классах:

class Square extends React.Component {
  constructor() {
    super()
    this.state = {
      value: null,
    }
  }
  render() {
    const { value, onClick } = this.props
    return (
      <button className="square" onClick={onClick}>
        {value}
      </button>
    )
  }
}

Потом явились функциональные компоненты:

const Square = ({ value, onClick }) => {(
  <button className="square" onClick={onClick}>
    {value}
  </button>
)}

В чём разница? Выкидываем: объявление класса, constructor(), render(), const для деструктуризации props, this. А ещё исчезло состояние компонента — мы получаем stateless functional components.

Как дальше жить без локального состояния: 1) или применять функциональные компоненты только там, где не нужно хранить состояние; 2) или перенести всё состояние в стор redux-а (как единственный источник правды). Локальные состояния компонентов — это дополнительный уровень абстракции, требующий обслуживания. А зачем?

Ещё желательно преодолеть коннектобоязнь — не тащить все свойства через родительские компоненты, а применять connect() для дочерних компонентов по мере использования свойств.

Разобрались, а как же применить PureComponent [2] к функциональным компонентам? На помощь приходит техника Higher-Order Components [3]:

// utils.js
import React from 'react'

export const pureComponent = (fn) => {
  class Wrapper extends React.PureComponent {
    render() {
      return fn(this.props, this.context)
    }
  }
  // не надо, т.к. подписывает на контекст как и функциональный компонент,
  // так и оболочку-PureComponent; лучше назначать сразу оболочке (снаружи)
  // Wrapper.contextTypes = fn.contextTypes
  Wrapper.displayName = fn.name
  return Wrapper
}

Присваивание displayName — для красоты в React DevTools. Подробнее про contextTypes можно почитать тут [4].

Пример использования:

import { pureComponent } from 'utils'

const Square = ({ value, onClick }) => {(
  <button className="square" onClick={onClick}>
    {value}
  </button>
)}

export default pureComponent(Square)

Рекомендуемые статьи

Автор: comerc

Источник [7]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/javascript/252859

Ссылки в тексте:

[1] тут: https://sourcegraph.com/github.com/comerc/yobr/-/blob/src/components/PostForm/PostForm.js

[2] PureComponent: https://habrahabr.ru/company/redmadrobot/blog/318222/

[3] Higher-Order Components: https://facebook.github.io/react/docs/higher-order-components.html

[4] тут: https://facebook.github.io/react/docs/context.html

[5] Стрелочные функции: https://habrahabr.ru/company/mailru/blog/213455/

[6] Руководство по работе с Redux: https://habrahabr.ru/company/mailru/blog/303456/

[7] Источник: https://habrahabr.ru/post/326610/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best