Перерисовка компонентов
• pure
• проверяет shallowEqual
• может работать медленно, если state и props объемные
• ложно-положительные срабатывания
• shouldComponentUpdate
• реализуем сами
• дает больше контроля
9
Принцип разделения ответственности
• Эдсгер Дейкстра, “On the role of scientific thought”, 1974
• Крис Рид, «Элементы функционального
программирования», 1989
• программа разделяется на секции, ответственные за
определенные области бизнес-логики
11
Slide 12
Slide 12 text
Компонент высшего порядка (HOC)
12
const Name = () =>
46
const ProductList = ({ currentUser, loading, products }) => {
if (!currentUser) {
return
}
if (loading) {
return
}
if (!products.length) {
return
}
return (...)
}
Еще раз про граничные условия
49
const mapStateToProps = state => ({
currentUser: getCurrentUser(state)
})
const enhance = compose(
connect(mapStateToProps),
branch(
({ currentUser }) => !currentUser,
renderComponent(NotAuthorized)
),
...
)
Еще раз про граничные условия
Slide 50
Slide 50 text
50
const checkAuthorization = compose(
connect(state => ({ currentUser: getCurrentUser(state) })),
branch(
({ currentUser }) => !currentUser,
renderComponent(NotAuthorized)
)
)
Еще раз про граничные условия
Slide 51
Slide 51 text
51
const enhance = compose(
checkAuthorization,
branch(
({ loading }) => loading,
renderComponent(Spinner)
),
branch(({ products }) => !products.length, renderComponent(NoData))
)
const ProductList = ({ products }) => (...)
export default enhance(ProductList)
Еще раз про граничные условия
Slide 52
Slide 52 text
52
const enhance = compose(
checkAuthorization,
branch(
({ loading }) => loading,
renderComponent(Spinner)
),
branch(({ products }) => !products.length, renderComponent(NoData))
)
const ProductList = ({ products }) => (...)
export default enhance(ProductList)
Еще раз про граничные условия
Slide 53
Slide 53 text
53
const showSpinnerWhileLoading = branch(
({ loading }) => loading,
renderComponent(Spinner)
)
Еще раз про граничные условия
Slide 54
Slide 54 text
54
const enhance = compose(
checkAuthorization,
showSpinnerWhileLoading,
branch(({ products }) => !products.length, renderComponent(NoData))
)
const ProductList = ({ products }) => (...)
export default enhance(ProductList)
Еще раз про граничные условия
Slide 55
Slide 55 text
recompose
• https://github.com/acdlite/recompose
• есть все функции, которые мы реализовали, и множество
других
• почти 10 000 звёд, хорошая поддержка
• flow
• RxJS
• TypeScript
• React Native
55
Slide 56
Slide 56 text
Простое e-commerce приложение
56
AddToCartButton – компонент, отвечающий за отрисовку кнопки для добавления товара в
корзину
redux + загрузка данных
• запрос выполняется вне компонента
• локального состояния нет
• не перерисовывать компонент, если ничего не изменилось
• по возможности – брать данные из store
78
Бенчмарки
90
100 HOCs, измеряем число обновлений в секунду
https://github.com/neoziro/recompact/tree/master/src/__benchmarks__
Slide 91
Slide 91 text
Производительность
• производительность может ухудшиться из-за появления
новых компонентов в дереве
• легче управлять перерисовкой компонентов
• многие компоненты реализованы в виде чистых функций
(без использования классов), в будущем возможна
оптимизация работы таких компонентов в React
91
Зачем нам HOC?
• убирать логику из presentational components и описать ее
декларативно
• повторно использовать presentational components в разных
частях приложения
• тестировать логику отдельно от представления
100
Slide 101
Slide 101 text
Что может пойти не так?
• нельзя использовать HOC внутри render (ок, не будем)
• статические методы придется копировать
• с refs работать неудобно (но можно)
• коллизии имен
101
https://reactjs.org/docs/higher-order-components.html#caveats
Slide 102
Slide 102 text
Зачем нам recompose?
• не писать кучу boilerplate-кода
• удобно управлять перерисовкой компонентов
• класть в props обработчики и переменные по мере
необходимости
• удобно обрабатывать граничные условия с помощью branch
102