Работа с Context в React

Работа с Context в React

От автора: React Context в настоящее время является экспериментальным API — но скоро он станет полноправным инструментом разработки! Есть много причин, по которым он представляет интерес, но, возможно, основные заключаются в том, что Context позволяет родительским компонентам неявно передавать данные своим потомкам, независимо от вложенности компонентов. Другими словами, данные могут быть добавлены к родительскому компоненту, а затем любой потомок может к ним подключиться.

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

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

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

Что делать, если нам не нужно, чтобы компонент Child содержал свойство на первом месте? Контекст позволяет нам обойти дочерний компонент и передать цвет непосредственно от Parent к GrandChild:

Хотя нам редко нужно отображать тот же цвет, где-нибудь внизу дерева компонентов. Ну, иногда нужно…

Но есть некоторые проблемы

Но в жизни не всегда все идет гладко, и Context в его текущем виде не исключение. Есть несколько основных проблем, с которыми вы, скорее всего, столкнетесь, если будете использовать Context для всех случаев, кроме самых простых.
Context отлично подходит для первоначального рендеринга. Обновление контекста «на лету»? Не так хорошо. Общей проблемой является то, что изменения Context не всегда отражаются в компоненте. Давайте разберем это более подробно.

Проблема 1: Использование PureComponent

Context трудно использовать с PureComponent, поскольку по умолчанию он не выполняет никаких по умолчанию с context. Shallow diffing, в отличие от PureComponent, проверяет, являются ли значения объекта строго равными. Если это не так, тогда (и только тогда) компонента будет обновляться. Но поскольку Context не задается явно, ну … ничего не происходит.

Проблема 2: Должен ли компонент обновляться? Возможно.

Context не обновляет компонента, если mustComponentUpdate компонента возвращает false. Если у вас есть собственный метод toComponentUpdate, то вам также необходимо учитывать Context. Чтобы включить обновления с помощью Context, мы можем обновить каждый отдельный компонент с помощью пользовательского shouldComponentUpdate, который выглядит примерно так.

Тем не менее, это не решает проблему промежуточного PureComponent между родительским и дочерним блоком обновления контекста. Это означает, что для каждого PureComponent между родителем и дочерним элементом должны быть определены contextTypes, и они также должны содержать метод toComponentUpdate. И на данный момент это требует очень большого объема работы, а выигрыш очень незначительный.

Подходы к решению проблем

К счастью, у нас есть несколько способов обойти эти проблемы.

Подход 1: Использование компонента более высокого порядка

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

Подход 2: Использовать свойства Render

Свойства Render позволяют использовать свойства, чтобы передавать код между двумя компонентами.

Подход 3: Включение зависимостей

Третий способ, с помощью которого мы можем обойти эти проблемы — использовать включение зависимостей для ограничения context API и разрешить компонентам подписываться на них при необходимости.

Новый Context

Новый способ использования context, который в настоящее время запланирован для следующего неосновного релиза React (16.3), будет более читаемым и удобными для записи без «проблем» предыдущих версий. Теперь у нас есть новый метод, называемый createContext, который определяет новый context и возвращает как Provider, так и Consumer.

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

В качестве дополнительного преимущества использования нового context нам больше не нужно использовать childContextTypes, getChildContext и contextTypes.

Разделяйте Contexts

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

Заключение

Context — это мощный API, но его также очень легко использовать неправильно. Кроме того, есть несколько предостережений относительно его использования, и вам может быть очень трудно определить, в чем проблема, когда что-то пойдет не так. В то время как компоненты более высокого порядка и включение зависимостей предлагают альтернативы для большинства случаев, Context может быть полезен в изолированных частях вашего кода.

Однако после выхода новой версии Context нам больше не нужно будет беспокоиться об этом. В ней будет устранена необходимость определять contextTypes для отдельных компонентов, что открывает возможности для определения новых повторно используемых Context.

Автор: Neal Fennimore

Источник: //css-tricks.com/

Редакция: Команда webformyself.

Метки:

Похожие статьи:

Комментарии Вконтакте: