Перейти к содержимому

Как называется метод для перерисовки содержимого компонента

  • автор:

Как называется метод для перерисовки содержимого компонента

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

Жизненный цикл компонентов в Angular 17

В процессе обновления компонента также срабатывают некоторые события жизненного цикла:

Жизненный цикл компонентов и события изменения компонента в Angular 17

Итак, компонент проходит следующие этапы жизненного цикла

  • конструктор : сначала выполняется конструктор компонентам
  • ngOnChanges : вызывается до метода ngOnInit() при начальной установке свойств, которые связаны механизмом привязки, а также при любой их переустановке или изменении их значений. Данный метод в качестве параметра принимает объект класса SimpleChanges , который содержит предыдущие и текущие значения свойства. Например, проверка изменений:

ngOnChanges(changes: SimpleChanges) < for (const inputName in changes) < const inputValues = changes[inputName]; console.log(`Previous $== $`); console.log(`Current $ == $`); console.log(`Is first $ change == $`); > >

Большая часть подобных методов определена в отдельном интерфейсе, который называется по имени метода без префикса «ng». Например, метод ngOnInit определен в интерфейсе OnInit . Поэтому, если мы хотим отслеживать какие-то этапы жизненного цикла компонента, то класс компонента должен применять соответствующие интерфейсы:

import < Component, OnInit, OnDestroy >from "@angular/core"; @Component(< selector: "my-app", standalone: true, template: 

Hello METANIT.COM

` >) export class AppComponent implements OnInit, OnDestroy < constructor()< console.log("constructor"); >ngOnInit() < console.log("onInit"); >ngOnDestroy() < console.log("onDestroy"); >>

ngOnInit

Метод ngOnInit() применяется для какой-то комплексной инициализации компонента. Здесь можно выполнять загрузку данных с сервера или из других источников данных.

ngOnInit() не аналогичен конструктору. Конструктор также может выполнять некоторую инициализацию объекта, в то же время что-то сложное в конструкторе делать не рекомендуется. Конструктор должен быть по возможности простым и выполнять самую базовую инициализацию. Что-то более сложное, например, загрузку данных с сервера, которая может занять продолжительное время, лучше делать в методе ngOnInit .

ngOnDestroy

Метод ngOnDestroy() вызывается перед удалением компонента. И в этом методе можно освобождать те используемые ресурсы, которые не удаляются автоматически сборщиком мусора. Здесь также можно удалять подписку на какие-то события элементов DOM, останавливать таймеры и т.д.

ngOnChanges

Метод ngOnChanges() вызывается перед методом ngOnInit() и при изменении свойств в привязке. С помощью параметра SimpleChanges в методе можно получить текущее и предыдущее значение измененного свойства. Например, пусть у нас будет следующий дочерний компонент ChildComponent:

import < Component, Input, OnInit, OnChanges, SimpleChanges >from "@angular/core"; @Component(< selector: "child-comp", standalone: true, template: `

Привет >

` >) export class ChildComponent implements OnInit, OnChanges < @Input() name: string = ""; constructor()< console.log("constructor"); >ngOnInit() < console.log("onInit"); >ngOnChanges(changes: SimpleChanges) < for (let propName in changes) < let chng = changes[propName]; let cur = JSON.stringify(chng.currentValue); let prev = JSON.stringify(chng.previousValue); console.log(`$: currentValue = $, previousValue = $`); > > >

И пусть этот компонент используется в главном компоненте AppComponent:

import < Component, OnChanges, SimpleChanges>from "@angular/core"; import < FormsModule >from "@angular/forms"; import < ChildComponent>from "./child.component"; @Component( ` >) export class AppComponent implements OnChanges < name ="Tom"; age = 25; ngOnChanges(changes: SimpleChanges) < for (let propName in changes) < let chng = changes[propName]; let cur = JSON.stringify(chng.currentValue); let prev = JSON.stringify(chng.previousValue); console.log(`$: currentValue = $, previousValue = $`); > > >

То есть значение для свойства name передается в дочерний компонент ChildComponent из главного — AppComponent. Причем в главном компоненте тоже реализован метод ngOnChanges() .

И если мы запустим приложение, то сможем заметить, что при каждом изменении свойства name в главном компоненте вызывается метод ngOnChanges:

OnChanges в Angular 17

В то же время надо отметить, что данный метод вызывается только при изменении входных свойств с декоратором @Input . Поэтому изменение свойства age в AppComponent здесь не будет отслеживаться.

Реализация всех методов

Определим следующий дочерний компонент:

import < Component, Input, OnInit, DoCheck, OnChanges, AfterContentInit, AfterContentChecked, AfterViewChecked, AfterViewInit>from "@angular/core"; @Component(< selector: "child-comp", standalone: true, template: `

Привет >

` >) export class ChildComponent implements OnInit, DoCheck, OnChanges, AfterContentInit, AfterContentChecked, AfterViewChecked, AfterViewInit < @Input() name: string = ""; count= 1; ngOnInit() < this.log(`ngOnInit`); >ngOnChanges() < this.log(`OnChanges`); >ngDoCheck() < this.log(`ngDoCheck`); >ngAfterViewInit() < this.log(`ngAfterViewInit`); >ngAfterViewChecked() < this.log(`ngAfterViewChecked`); >ngAfterContentInit() < this.log(`ngAfterContentInit`); >ngAfterContentChecked() < this.log(`ngAfterContentChecked`); >private log(msg: string) < console.log(this.count + ". " + msg); this.count++; >>

И используем этот компонент в главном компоненте:

import < Component>from «@angular/core»; import < FormsModule >from «@angular/forms»; import < ChildComponent>from «./child.component»; @Component( ` >) export class AppComponent

И при обращении к приложению мы получим следующую цепочку вызовов:

Простое и понятное введение в React Native

React Native является относительно простым фреймворком для разработки кроссплатформенных приложений для iOS и Android на JavaScript, но во многих введениях по нему материал даётся сложным и запутанным образом. Перед началом работы нужно что-то устанавливать, настраивать, выяснять необходимость наличия компьютер Mac и прочее. Официальная документация написана неплохо, но введение в React Native можно сделать проще и понятнее.

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

Нюансы фреймворка мы будем рассматривать на примерах из документации, чтобы в дальнейшем вам было удобнее с ней работать.

Рассмотрим простой пример.

Для создания приложений в React Native используется расширенный JavaScript стандарта ES2015.

import React from ‘react’;

необходима для поддержки JSX. JSX — это синтаксис, позволяющий встраивать XML в JavaScript. Если строку импорта убрать, то блок кода

будет помечен как ошибочный.

происходит подключение к проекту модуля Component. Без этой строки при создании класса пришлось бы указать export React.Component.

Далее в коде создаётся класс HelloWorldApp, который является компонентом. Обратите внимание на то, что наш класс содержит в себе дочерние компоненты — View и Text. Это нужно понимать при работе с контекстом.

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

Здесь LotsOfGreetings является родительским пользовательским компонентом, а Greeting — дочерним пользовательским компонентом, который выводит приветствие в зависимости от параметра name.

— это структурный элемент, соответствующий компоненту Greeting.

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

Передача данных от родительского компонента дочернему производится посредством параметров props. Когда родитель перерисовывает дочерний компонент, то он отправляет ему параметры. Они доступны через this.props.

Фигурные скобки <> используются для вставки кода javascript в JSX структуру. Блочный javascript комментарий в JSX также необходимо заключить в фигурные скобки:

Если требуется расширить функциональность какого либо встроенного компонента, например, Button, то для этого мы не раздуваем его функциональность при помощи добавления атрибутов и свойств, как это происхоит в html и javascript, а создаём новый компонент, наследующийся от базового Component. Можно написать и extends Button, но это не приведёт к наследованию от кнопки и создания кастомной кнопки. Внешний вид компонента и его функциональность задаются явно, а не наследуются от родительского класса, как будет видно далее.

Вернёмся к исходному примеру.

import < Text, View >from ‘react-native’;

подключает к проекту классы компонентов, использующиеся в нём: Text — текстовая область и View — контейнерный компонент.

В каждом классе компонента необходимо определить метод render(), предназначенный для отрисовки его содержимого. Данный метод должен вернуть либо элемент React, либо null, если ничего отрисовывать не нужно.

В контексте React Native компоненты являются виджетами — объектами, имеющими видимое представление. Под отрисовкой (рендерингом) компонента понимается преобразование движком React Native разметки JSX в нативный вид путём вызова соответствующих методов API. В результате на экране устройства мы видим нативный интерфейс, а не его имитацию средствами web. При этом полученный интерфейс на iOS и Android будет отличаться. То есть, данный фреймворк не позволяет создать интерфейс, одинаково отображающийся и на iOS, и на Android.

Вся разметка компонента должна находиться в одном корневом контейнерном элементе. Следующий код вызовет ошибку:

Для устранения ошибки второй контейнерный элемент нужно вложить в первый.

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

Контейнерные и неконтейнерные элементы можно задать в форме самозакрывающегося тега:

Настройка компонентов происходит при помощи параметров двух видов — props (начальные неизменяемые параметры) и state (изменяемое состояние). Props часто называют свойствами, но это вносит путаницу так как под свойствами мы привыкли понимать изменяемую сущность. Тогда что это, атрибут, реквизит, свойство для чтения? Props следует понимать как параметры, которые можно передать компонентам в момент их создания и которые остаются фиксированными на протяженни всего жизненного цикла компонента. В примере

title является встроенным обязательным параметром, который нужно указать. Значение данного параметра можно получить, но его изменение не изменит надписи на кнопке:

this.props.title = «Новая кнопка»; // надпись на кнопке останется прежней — «Кнопка»

Более того, при перерисовке компонента (которое происходит при каждом изменении его состояния, о чём будет рассказано далее, изменении контекста или получении props от родителя) значения параметров сбрасываются в начальное состояние. Например, мы решили ввести свой параметр myParams:

Где-то в коде можно будет обратиться к нему и изменить его значение:

В другом месте кода можно будет его использовать, но при перерисовки компонента значение this.params.myParams останется равным «100».

Наряду со встроенными параметрами, которые изначально имеют встроенные компоненты, можно использовать пользовательские параметры при создании пользовательского компанента:

, где name — пользовательский параметр

или в конструкторе компонента:

constructor(props) super(props)
this.props.title = ‘myTitle’
>

Для доступа к параметру внутри JSX используются фигурные скобки:

Как изменить значение параметра (например, title), если оно является неизменяемым? Для этого используется состояние state. Данные, которые нужно изменить, необходимо преобразовать в состояния:

title — это параметр, а myTitle — это состояние, определённое в конструкторе так:

Имя состояния можно не заключать в кавычки. Если состояний несколько, то они перечисляются через запятую:

this.state = ‘myTitle’:’Показать приветствие’,
‘name’:’Mate’,
‘age’:’25’
>

Преимущество данной записи состоит в том, что в случае организации цикла по свойствам компонента, в объект state попадут все указанные состояния. Если каждое состояние будет задано в отдельной строке при помощи this.state, то в выборку попадёт состояние, определённое последним.

Для получения состояни используется запись this.state.myTitle, а для изменения состояния используется метод setState:

Изменение состояния должно производиться только при помощи указанного метода. При любом изменении состояния компонента вызывается его метод render(). Каждое каждое лишнее действие в данном методе будет влиять на скорость отрисовки. При помощи специального метода можно откелючить перерисовку компонента.

В терминах React Native компонент может иметь много изначально заданных параметров (props), но находить в каждый момент времени в одном состоянии (state). При работе с компонентом мы меняем его состояние, а не параметры (или свойства). Предположим, в момент создания кнопка имеет какую-то надпись. Это значит то, что кнопка находится в состоянии отображения данной надписи. Если при помощи состояния надпись или её цвет были изменены, то это означает то, что теперь кнопка находится в другом состоянии с изменённой надписью или её цветом. Аналогичным образом можно описать состояние всех компонентов в проекте.

Атрибут ref

Вернёмся к кнопке:

Текущее значение параметра title в нашем случае можно получить при помощи состояния this.state.myTitle. Но как получить значение параметра title, если ему была присвоена строка? Для этого используется атрибут ref, принимающий функцию обратного вызова, параметром которого является ссылка на компонент, в котором она используется:

Теперь ссылка this.myButton будет указывать на компонент Button и можно будет получить значение его параметра title так:

или обратиться к методу компонента:

Рассмотрим более сложный пример c использованием стилей и событий.

Стили похожи на CSS, но фреймворк не использует CSS, хотя и заимствует многое из web разработки. Стиль представляет собой объект. При использовании встроенного стиля он заключается в двойные фигурные скобки, так как объекты в javascript заключаются в фигурные скобки:

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

У функции стрелки отсутствует свой контекст, поэтому внутри данной функции this будет таким же, как и снаружи. При вызове обычной функции внешний контекст this не передаётся и, соответственно, внутри функции нельзя обратиться к параметрам и состоянию компонента. Если это и не требуется, то можно использовать вызов функции без привязки контекста:

Если внутри функции требуется контекст, то используется вызов с привязкой:

Здесь под this понимается контекст родительского компонента, а не дочернего элемента , как может показаться. В методе _onPress компонента невозможно получить значение параметра title элемента . Для ссылки на параметр элемента (дочернего компонента) необходимо получить ссылку на него при помощи атрибута ref, как было показано выше.

Для вызова функции с контекстом и параметрами последние перечисляются после this через запятую:

Пользовательские аргументы передаются функции перед системными. При возникновении события onValueChange система передаёт функции обработки один параметр, в котором находится название выбранной опции компонента Picker. Тогда в первом параметре функции updateUser будет находится строка ‘Привет’, а во-втором — название выбранной опции.

Для уменьшения накладных расходов привязку можно заранее сделать в конструкторе и использовать состояние в качестве параметра:

constructor(props) super(props);
this.state = ;
this.updateUser = this.updateUser.bind(this,this.state.name);
>

Обратите внимание на то, что при использовании функции стрелки можно получить оба параметра, передаваемых системой обработчику события onValueChange — название выбранной опции и её индекс, тогда как использовании обычной функции системой передаётся один параметр — название выбранной опции.

При изменении выбранного элемента Picker система вызывает встроенный метод onValueChange. Аналогичным образом в дочернем компоненте можно создать свой метод и затем вызвать его. Для этого создаём метод:

_onMySend = (par) => Alert.alert(par)
>

Добавляем его дочернему элементу в качестве параметра, например, onSend:

А где-нибудь в дочернем компоненте вызываем наш метод:

Упростим вызов метода при помощи деструктуризации объекта:

const = this.props;
onSend(‘Параметр 1’)

Параметры props используются не только для хранения в них неизменяемых данных, но и в качестве ссылок на методы. Проще говоря, в элементе:

title и onPress являются параметрами props.

Как динамически добавить или удалить компонент? Для этого можно изменить состояние компонента, сделав его видимым или невидимым, или настроить отображение компонентов в функции отрисовки render(), которая в зависимости от того или иного условия будет отрисовывать нужную компонентную структуру. Разметка в React Native производится при помощи Flexbox.

В основе React Native лежит JavaScript и кажется, что это позволяет использовать такие же трюки и фокусы, как и в web разработке. Но это не так. И на мой взгляд основная сложность фреймворка как раз и заключается в понимании этого. На JavaScript объекты, методы и свойства можно создавать «на лету», есть возможность напрямую взаимодействовать со свойствами и др., а здесь используется традиционный подход к разработке приложений, при котором работа происходит в рамках определённой компонентной структуры, а не динамически создаваемой и загружаемой, как в web среде.

Мышление в стиле React

Не думайте о React, как о библиотеке, которая делает за разработчика его работу — это не так. Разработчику совсем без опыта так и разработчику со стажем стоит понимать основополагающие концепции, о которых и поговорим в статье. Задачами библиотеки выступают: во-первых, построение пользовательских интерфейсов, и, во-вторых, способы работы с информацией. В конечном итоге эти две задачи определяют архитектуру приложений и определяют, как мы разрабатываем приложения. Об этом напишу по порядку.

Больше интересного у меня на канале.

Декларативный подход

Как писалось выше, идея React — это удобство описания UI. Библиотека дает API, с помощью которого можно декларативно описывать интерфейсы без прямых манипуляций с DOM деревом. А сама библиотека берет на себя функцию по перерисовке состояний приложения. Процедуры перерисовки оптимизированы внутри приложения с помощью сложных алгоритмов и оптимизаций.

Для работы с DOM деревом React использует концепцию Virtual DOM. Virtual DOM выступает представлением браузерного DOM деверева в виде объекта, который хранит информацию о каждом элементе. Библиотека берет на себя функцию сравнения деревьев, за это отвечает механизм сравнения — reconciliation.

Этот подход носит декларативный характер и означает, что пишите внутри создаваемых компонентов только то, что будет в конечном результате в интерфейсе, а не то как будете это делать. Иными словами, не прописываем процесс отрисовки. Остальную работу выполнит React.

Компоненты — как краеугольных камень идеи React

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

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

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

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

Чтобы показать на практическом примере, возьмем страницу Medium и разберем возможный способ разбить страницу на отдельные компоненты с использованием React:

Выделяются крупные блоки:

  • шапка страницы с логотипом, навигацией и меню
  • блок с контентом страницы, который включает статьи и правый блок с подборкой популярный статей:

Так тогда и опишем с помощью React структуру и добавим указанные блоки в корневой компонент App:

Красным выделен следующий уровень компонентов, поэтому если создадим новый компонент Header, то его структура выглядела бы следующим образом:

Представим, что для статей приходит некий массив объектов, назовём его условно articleList, в котором хранятся данные для отображения содержимого. Для отображения на странице воспользуемся привычным методом map:

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

Поэтому если мы видим, что компонент динамически изменяется, и видим в коде этого компонента только статичные props, то стоит двигаться по иерархии вверх от родителя к потомку и в конечном итоге увидим компонент со state.

Такой способ работы с данными упрощает работу и библиотеке, и разработчикам, приложение делается предсказуемым. Изменения props или state вызывают перерисовку компонента и служат триггерами для перерисовки. Стоит также учитывать, что излишние перерисовки нагружают приложение и проседает производительность, поэтому отслеживайте и пресекайте подобные вещи.

Конечно, описанные сценарии не охватывают всех возможностей React, но определяют работу с библиотекой. Процессы отрисовки структуры компонентов становятся явными. При этом передача информации между ними тоже понятна.

Итого

  1. React — это в первую очередь работа с отрисовкой UI и с этой задачей библиотека справляется за счет внутренних алгоритмов и сценариев
  2. Чтобы понимать, как устроены большинство React приложений — усвойте концепцию модульности и компонентного подхода.
  3. Передача данных напрямую происходит с помощью props от родительского компонента к потомку, и в обратном порядке через вызовы переданных функций.
  4. За динамику и интерактивность в React отвечает state, изменение state и props являются триггерами перерисовки любого компонента.
  5. Контролируйте перерисовки компонентов — это на прямую влияет на производительность приложения.

Если понравилась история, то подпишись на мой Телеграм канал

Ссылки:

  1. https://ru.reactjs.org — Официальная страница React

Почитать еще:

  1. Какой JavaScript фреймворк или библиотеку выбрать для изучения в 2020 году?
  2. Рекурсивный обход DOM дерева
  3. Подробное руководство по JSX. Часть 1. Общее понимание работы.

Хук useContext — JS: React Hooks

React передает данные внутрь компонентов с верхних уровней на нижние, используя пропсы.

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

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

Хук useContext() позволяет использовать контекст внутри компонента. Для этого нужно выполнить три действия:

    Инициализировать контекст в том же месте, где инициализируется приложение

// Параметром передается значение по умолчанию // Имя контекста выбирается произвольно const UserContext = React.createContext(<>); 
// user — данные которые лежат внутри контекста UserContext.Provider value=user>> MyComponent /> UserContext.Provider> 
import React,  useContext > from 'react'; const MyComponent = () =>  // Возвращает контекст целиком const user = useContext(UserContext); return h1>user.name>h1>; > 

Вот другой пример контекста, в котором хранится текущая тема:

const themes =  light:  foreground: '#000000', background: '#eeeeee', >, dark:  foreground: '#ffffff', background: '#222222', >, >; const ThemeContext = React.createContext(<>); 

И где-то внутри приложения:

ThemeContext.Provider value=/* текущая тема */>> Content /> ThemeContext.Provider> 

Метод React.createContext() принимает значение по умолчанию. Это значение будет передаваться в контекст тех компонентов, которые не обернуты в провайдер. Обычно провайдер всегда используется, чтобы оборачивать все приложение. Поэтому компоненты всегда принимают в контексте значение, переданное провайдером. Но если мы работаем с компонентом вне провайдера, может понадобиться такое значение по умолчанию. Например, такая ситуация может сложиться при тестировании компонента отдельно от приложения.

Внутри контекста может храниться как примитивное значение, так и объект. Изменение содержимого такого объекта никак не отслеживается React, поэтому не приводит к перерендеру. Но если заменить сам объект, то из-за изменившейся ссылки React узнает об изменении и выполнит перерисовку компонентов внутри провайдера.

Иногда возникает ситуация, когда в контексте нужно хранить динамические данные. Например, при авторизации. Когда пользователь авторизован, мы должны сохранить какие-то данные, чтобы пользователю предоставлялись дополнительные функции. Сам по себе контекст для этого ничего не предоставляет, но можно передать в контекст методы для манипулирования данными, а сами данные хранить с помощью useState() . Более продвинутый вариант — это создать провайдер в отдельном компоненте. Так мы сможем изолировать данные от всего приложения, а в компоненты передавать интерфейс для взаимодействия с данными.

Для этого создадим контекст в отдельном модуле, чтобы все компоненты могли его импортировать:

// ThemeContext.js import  createContext > from 'react'; export default createContext( themes: <>, theme: <>, setTheme: () => <>, >); 

Создаем отдельный компонент провайдера:

import ThemeContext from './ThemeContext.js'; const themes =  light:  foreground: '#000000', background: '#eeeeee', >, dark:  foreground: '#ffffff', background: '#222222', >, >; const ThemeProvider = ( children >) =>  const [theme, setTheme] = useState(themes.dark); const setLightTheme = () => setTheme(themes.light); const setDarkTheme = () => setTheme(themes.dark); return ( ThemeContext.Provider value= theme, setLightTheme, setDarkTheme, themes >>> children> ThemeContext.Provider> ); >; 

И внутри приложения используем провайдер как обычный компонент:

ThemeProvider> MyComponent /> ThemeProvider> 

В самом компоненте теперь можно импортировать контекст и использовать функции из провайдера для изменения состояния в контексте:

import React,  useContext > from 'react'; import ThemeContext from './ThemeContext.js'; const MyComponent = () =>  const  setLightTheme > = useContext(ThemeContext); return button onClick=() => setLightTheme()>>Включить светлую темуbutton>; > 

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов

Наши выпускники работают в компаниях:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *