Управление данными вашего приложения, используя API API-контекста RACT, это весело и просто для реализации!
Тем не менее, это также может стать кошмаром, если не обрабатывается с осторожностью, особенно как ваше приложение растет в размере.
В качестве разработчика реагирования вы не можете делать без передачи данных в вашем приложении React. И если вы просто начинаете с реагирования, вы, скорее всего, будете делать то, что называется «бурением для бурения».
Это связано с вручную получать данные из компонента A до компонента C и D через реквизиты. Где компонент A является обычным родителем C и D.
Это нормально, если вы имеете дело с простом приложением.
Но по мере роста вашего приложения вы обнаружите, что передача этих данных несколько компонентов вниз (от родителя к глубоко вложенным дочерним компонентом) больше не весело. И вы можете засвидетельствовать несколько компонентов, которые служат только маршрутом для передачи этих данных. В этом случае данные являются неактуальными для компонента как таковой.
Чтобы обойти это, реагирование предоставляет нам контекст API.
Что такое API-контекст React
API контекста в React позволяет каждому компоненту в дереве компонентов иметь доступ для потребления данных без необходимости вручную пройти к нему.
Преимущество здесь заключается в том, что вы получите вырезать компоненты «посредника». Это означает только компонент, который нуждается в данных, об этом знают.
Вот как это работает.
У вас будет место (например, магазин), где будут жить ваши глобальные данные. Затем вы настроите логику, чтобы открыть эти данные, чтобы любой компонент мог легко получить и получить его.
Давайте посмотрим, как мы можем достичь этого практически.
Мы будем работать с проектом (в данном случае, простым приложением TODOS), где у нас есть глобальные данные (в родительском компонентах), получавшем доступ к его детскому компоненту через реквизиты.
В этом учебное пособие по контексту React вы узнаете, как управлять этими данными, используя контекстный API. Вы также получите возможность посмотреть подводные камни с использованием контекста Ractex и почему вы не должны идти на это слишком рано.
Получение файлов проекта готовы
Мы начнем, потянув наши начальные файлы проекта Из этого Github Repo Отказ Идите вперед и клонируйте проект, запустив эту команду из своего терминала:
git clone https://github.com/Ibaslogic/simple-todo-app
Это создаст каталог во имя папки проекта.
После того, как у вас будут загруженные файлы проекта и папки, откройте его с помощью текстового редактора и запустите:
npm install
Убедитесь, что вы находитесь внутри каталога проекта, прежде чем запустить вышеуказанную команду.
Команда установит все необходимые зависимости в локальном Node_Modules папка. После этого начните свой сервер разработки, запустив:
npm start
Вы должны увидеть приложение в адресной строке вашего браузера в localhost: 3000.
Вы можете узнать, как создать это приложение с нуля, следуя это руководство по ориентированию на реагирование . Там мы использовали «реквизит бурения» для потока данных.
Изображение выше показывает четкое изображение иерархии компонентов. Как и ожидалось, вы должны знать, что компонентные файлы для приложения живут в SRC/Компоненты папка.
TodoContainer является родительским компонентом, который содержит все другие детские компоненты. Его файл содержит данные TODOS, которые обращаются к компоненту детей через реквизиты.
Аналогично, у него есть пара классов методов, которые также нуждаются в доступе к данным штата Тодос.
Если вы следите за Это руководство Или знакомство с реагированием, вы должны знать, почему мы поднимаем состояние полностью до родительского компонента. Чтобы подтвердить, для каждого компонента доступа к данным состояния, Государство Объект объявлен в файле их ближайшего общего родителя.
Мы делали то, что называется государственным подъемом! Ничего особенного, то есть основной реагирование.
Теперь, от дерева компонентов вы можете вывести, что у нас есть только два слоя, из которых мы передаем данные. От Тодоскайнер Компонент к Тодослист а потом к Todositem. .
В этом случае вручную передавая данные с помощью реквизитов желательно/рекомендуется.
Но если вы обнаружите, что опорное бурение становится проблемой – то есть вы передаваете данные через реквизиты во многие вложенные компоненты, делая некоторые компоненты только в качестве маршрута. Затем используя API контекста лучше.
Чтобы увидеть контекст API в действии, мы все равно будем работать с этим приложением TODOS.
Но имейте в виду, что контекст желательно, если бурение реквизита становится проблемой (это не так с этим приложением).
Опять же, вы не должны идти на контекст слишком рано.
Вы узнаете, почему позже в этом руководстве. Продолжай читать!
Настройка контекста
Как я уже упоминал ранее, мы создадим центральный магазин, где будут жить наши глобальные данные. Итак, давайте создадим новый файл под названием context.js в SRC папка. В этом файле добавьте следующий исходный код:
import React, { Component } from "react"
const TodosContext = React.createContext()
const TodosProvider = TodosContext.Provider
// const TodosConsumer = TodosContext.Consumer
class MyContext extends Component {
render() {
return (
{this.props.children}
)
}
}
export { TodosContext, MyContext }
Далее иди внутрь SRC/index.js Файл и оберните родительский компонент, TodoContainer С компонентом контекста Mycontext Отказ Убедитесь, что вы импортируете файл контекста.
...
import { MyContext } from "./context";
ReactDOM.render(
,
document.getElementById("root")
);
Сохраните файлы.
Что происходит?
В контексте мы начали с создания объекта контекста, который мы присваиваемым для Тодосконтестки переменная. Здесь вы можете передавать значение контекста по умолчанию или просто пройти пустое значение, как видно выше.
Теперь вам может быть интересно: «Почему компонент класса? Это год 20xx, почему бы не использовать крючок в функциональном компоненте ».
Независимо от типа компонента (класса или функции), подход к созданию объекта контекста одинаково.
Более того, фокус находится на контексте API, а не тип компонента. Также помните, что есть люди, которые все еще используют компонент класса.
Вы все еще не хотите использовать какой-либо комбинационный компонент?
У меня есть Накрыл, как вы можете написать это же приложение ToDos только с функциональным компонентом, используя реактивный крюк. Вы можете быстро пройти через него и вернуться, чтобы продолжить этот контекстный учебник.
Тебе решать!
Двигаться дальше.
После того, как у вас есть этот объект контекста, у вас есть доступ к двум компонентам – Провайдер и Потребитель Отказ Поставщик контекста Ractex позволяет всем компоненту в дереве иметь доступ, чтобы потреблять данные контекста.
Но не до тех пор, пока вы не упаковываете компоненты, которые нуждаются в доступе к этим данным или их общим родителям (в нашем случае, Todocontainer ) с ним.
Это говорит вам, что вы также можете обернуть провайдер вокруг компонентов в Todocontainer.js. файл.
Как разработчик реагирования, вы должны знать, почему мы используем дети опоры в context.js файл.
Как преодоление, This.props.children Как используется в Mycontext Компонент является JSX/компонентом, пройденный между Теги в index.js Файл – я Отказ
Провайдер Как видно в контексте, файл, принимает ценность опоры, где мы разместим все наши данные. Тем временем мы проходим простую строку. Позже мы пройдем целый объект.
На данный момент ничего не изменилось в нашем приложении!
Давайте посмотрим, как мы можем получить доступ/потреблять значение контекста из любого из компонентов детей.
Доступ к данным контекста
В зависимости от типа компонента, есть разные способы, которыми вы можете получить доступ к вашему контекстному данным. Мы начнем с доступа к этим данным в компоненте класса. Позже вы узнаете, как достичь то же самое в функциональном компоненте, а также через реактивный крюк.
Не забывайте, как Провайдер У нас также есть доступ к Потребитель Отказ Но на данный момент мы прокомментировали это, как видно в context.js файл. Мы приедем к этому, когда нам нужно получить доступ к нашим данным в компоненте функции.
Доступ к данным контекста (используя ContextType) в компоненте класса
Открыть SRC/Компоненты/ToDoslist.js Файл и импортировать объект контекста, Тодосконтестки вот так:
import { TodosContext } from "../context"
Добавьте это выше Визуализация () Метод:
static contextType = TodosContext;
И это внутри Визуализация () Метод, но над вернуть утверждение.
const value = this.context console.log(value)
Сохраните свой файл и проверьте консоль своих devtools.
Как вы можете видеть, мы получаем данные, назначенные для ценность опоры (в файле контекста) здесь в этом Тодослист составная часть.
Что только что произошло?
В коде мы начали с помощью инициализации ContextType используя статический класс. Затем мы назначили ему объект контекста, который мы создали ранее. Оттуда у нас есть доступ к нашему ценность через this.context Отказ
На данный момент мы проходим простую строку к ценность пропры Вместо этого мы пройдем все данные TODOS, которые у нас есть в Государство объект нашего приложения.
Так что на данный момент скопируйте Государство объект из TodoContainer компонент и вставьте его выше Визуализация () Метод в context.js файл.
Примечание: пожалуйста, скопируйте, чтобы избежать перерыва страницы. Мы будем удалять его позже.
Так что у тебя есть:
...
import { v4 as uuidv4 } from "uuid";
...
class MyContext extends Component {
state = {
todos: [
{
id: uuidv4(),
title: "Setup development environment",
completed: true,
},
{
id: uuidv4(),
title: "Develop website and add content",
completed: false,
},
{
id: uuidv4(),
title: "Deploy to live server",
completed: false,
},
],
};
render() {
return (
{this.props.children}
);
}
}
...
Не забудьте обновить ценность опоры в <Тодоспровидер> Отказ
Если вы сохраните свой файл и еще раз проверьте консоль, вы увидите данные TODOS.
В ценность Пропор, мы теперь передаем все данные состояния TODOS, которые мы получаем с использованием оператора распространения, ... это .state Отказ
Теперь, когда ценность У опоры есть эти данные, его можно потреблять от любого из компонентов детей в дереве.
Далее давайте переместим все методы класса из Todocontainer.js Файл также к context.js сделать их глобально доступным. Вырезать и вставить их над Визуализация () метод.
Теперь мы можем разоблачить эти методы (так же, как мы сделали для Offief Conture объект), так что другие компоненты на дереве могут иметь доступ.
Так обновите ценность опоры в компоненте провайдера, чтобы включить такие методы, как так:
...
render() {
return (
{this.props.children}
);
}
...
Теперь вы можете удалить Государство объект в Todocontainer.js Файл (помните, что мы перевели его на context.js файл) и удалите все реквизит связан со всеми тегами компонентов.
Ваш Todocontainer.js Файл должен теперь выглядеть так:
import React from "react"
import TodosList from "./TodosList"
import Header from "./Header"
import InputTodo from "./InputTodo"
class TodoContainer extends React.Component {
render() {
return (
)
}
}
export default TodoContainer
Как вы можете видеть, у нас больше нет реквизит было передано, чтобы получить подкомпонент Data Dish. Все компоненты теперь имеют доступ к употреблению данных, которые доступны в context.js файл.
Теперь у нас есть чистый код.
Если вы сохраните свои файлы и проверьте интерфейс, вы увидите перерыв на странице. Это потому, что Тодолист Компонент по-прежнему ссылается на его родительский компонент, чтобы получить данные TODOS.
Исправление это просто.
Как вы знаете, данные доступны в этом компонент через контекст. Все, что вам нужно сделать, это указать на то, где он сохранен и захватить его.
Итак, измените Todoslist.js файл так что у тебя есть:
import React from "react"
import TodoItem from "./TodoItem"
import { TodosContext } from "../context"
class TodosList extends React.Component {
static contextType = TodosContext
render() {
const value = this.context
return (
{value.todos.map(todo => (
))}
)
}
}
export default TodosList
Так как данные TODOS сохранены в ценность Переменная, мы обращались к ней и процитировали как ожидалось. Уведомление, Экземпляр в этом файле больше не служит пути для передачи данных.
Сохраните файл и проверьте интерфейс. Вы должны увидеть ваше приложение.
Просто как тот.
Теперь вы знаете, как получить доступ к данным контекста в компоненте класса. Многие все еще должны быть исправлены в этом приложении. Но мы куда-нибудь направляемся.
Доступ к данным контекста в компоненте функции
С Введение реактивный крюки Теперь вы можете иметь весь свой компонент приложения только с функциональным компонентом. В связи с этим, зная, как получить доступ к этим данным в этом типе компонента очень важно.
Как вы знаете, это приложение построено только со компонентами класса. Хотя я покрыл Как вы можете построить это с функциональным компонентом . Вы можете взглянуть быстро, если вам нужен переподготовка.
Что это говорит вам, это то, что нам нужно преобразовать один из компонентов в тип функции, чтобы увидеть, как мы можем получить доступ к контекстам данных.
Это должно быть прямо вперед.
Открыть SRC/Компоненты/ToDoitem.js Файл и замените компонент класса с помощью этого функционального компонента.
import React from "react"
const TodoItem = props => {
const completedStyle = {
fontStyle: "italic",
color: "#d35e0f",
opacity: 0.4,
textDecoration: "line-through",
}
const { completed, id, title } = props.todo
return (
Это это для преобразования. Если вы царапаете голову, пожалуйста, быстро пройдите последнюю ссылку и узнайте, как сделать это преобразование.
Теперь давайте посмотрим, как получить доступ к данным контекста в этом компоненте.
Если вы посмотрите на Onchange и OnClick Обработчик событий в этом файле мы обращаемся к HandleChange и Deltodo Методы от родительского компонента через реквизиты. Теперь у нас есть эти методы, доступные в context.js файл.
Давайте доступ к ним.
Поскольку мы имеем дело с функциональным компонентом, более ранний метод, используемый в компоненте класса, не применяется. Вместо этого мы будем использовать Потребитель составная часть. Этот компонент позволяет получить доступ к контекстам в рамках функционального компонента.
Помните, это Потребитель Компонент присутствует в файле контекста.
Так что идитеруйте в файл и безотлагали эту линию.
// const TodosConsumer = TodosContext.Consumer
Затем обновите Экспорт Чтобы включить его так:
export { TodosContext, MyContext, TodosConsumer }
Сохраните файл.
Вернуться к Todoitem.js Файл, импортировать Тодоссумитель из файла контекста.
import { TodosConsumer } from "../context"
Затем обновите вернуть Заявление, так что у вас есть:
... return ({(value) => { console.log(value); return ( ); ...props.handleChangeProps(id)} /> {title} ); }}
Этот метод доступа к контексте данных использует то, что называется Рендер опора Отказ Вам не нужно учиться его использовать его.
Это очень просто и прямо вперед.
Тодоссумитель требует функции как ребенок, который принимает ценность аргумент Это ценность Держит весь контекстный объект, назначенный для ценность Подп провайдера.
Давайте сохраним файл и проверьте консоль, чтобы увидеть, что ценность Держит (так как мы регистрируем Value в коде).
Теперь, когда мы получаем данные, давайте обновим вернуть заявление для их использования.
return ({value => { const { handleChange, delTodo } = value return ( )handleChange(id)} /> {title} ) }}
С деструктурированием объекта JavaScript мы извлекаем HandleChange и Deltodo Методы из ценность аргумент
Затем мы заменили ropps.handleChangeProops. и ropps.deletoDOronops. с HandleChange. и Deltodo соответственно.
Сохраните файл.
Теперь вы знаете, как получить доступ к данным контекста в функциональном компоненте.
Вы должны быть в состоянии переключать флажки и удалить элементы TODOS. Но вы еще не можете отправить ToDos. Мы доберемся до этого.
Двигаться дальше.
Доступ к контексту реагирования с крюком
Здесь также мы будем работать с функциональным компонентом. Но на этот раз в гораздо проще. Метод крюка.
Это мой предпочтительный метод. Очень просто и лаконично.
Мы посмотрим на компонент, который контролирует поле ввода и представление. Так что откройте Inputtodo.js файл. К сожалению, этот компонент основан на классе. Значение, нам нужно будет преобразовать его в функцию для использования крючка.
Если вы Следуйте моим учебным пособистре по крюку Это преобразование должно быть куском пирога.
Здесь у вас есть:
import React, { useState } from "react"
const InputTodo = props => {
const [inputText, setInputText] = useState({
title: "",
})
const onChange = e => {
setInputText({
...inputText,
[e.target.name]: e.target.value,
})
}
const handleSubmit = e => {
e.preventDefault()
props.addTodoProps(inputText.title)
setInputText({
title: "",
})
}
return (
)
}
export default InputTodo
Хорошо.
Теперь давайте обновим Inputtodo.js файл для использования контекста.
Вы должны иметь:
import React, { useState, useContext } from "react"
import { TodosContext } from "../context";
const InputTodo = props => {
const value = useContext(TodosContext);
const { addTodoItem } = value;
...
const handleSubmit = e => {
e.preventDefault()
addTodoItem(inputText.title)
setInputText({
title: "",
})
}
return (
...
)
}
export default InputTodo
Обратите внимание, как мы изменили Handlesubmit функция. Вместо того, чтобы передать addodoitem Метод через опоры, как указано ранее, мы употребляем этот метод непосредственно из контекста.
Реагирование дает нам упреждающий текст Крюк для чтения контекстных данных внутри функционального компонента. Все, что вам нужно сделать, это пройти вдоль вашего объекта контекста в качестве аргумента.
Это прямо вперед. Как вы можете видеть, с одной линейкой кода у нас есть данные контекста, готовые к использованию. Оттуда мы получаем addodoitem (нужен в Handlesubmit Функция) путем разрушения ценность .
Совет: используйте функциональный компонент, если вы хотите получить доступ к контексту вне класса оказывать() метод.
Вы можете сохранить свой файл и проверить ваше приложение.
Это должно работать, как ожидалось.
Проблема производительности с API-контекстом React
Реагнийный контекст известен для рендеринга компонентов, которые потребляют данные контекста каждый раз, когда ценность Опирая изменяется в контексте.
Что я имею в виду?
Всякий раз, когда ценность Из изменений контекста потребительский компонент, который запускает изменения, повторно представляют, чтобы получить обновленное значение. Это нормально.
Но повторное рендеринг не будет ограничен этим потребительским компонентом в одиночку, но все компоненты, которые обращаются к контексту.
Хотя это может привести к малому вопросу о производительности в небольшом приложении, оно не может быть упущено, особенно если ваше приложение становится сложным.
Давайте посмотрим на эти проблемы в нашем приложении.
Мы будем регистрировать текст во всех компонентных файлах.
Начиная с SRC/Компоненты/ToDocontainer.js файл. Добавьте это выше вернуть утверждение:
console.log("TodoContainer is running")
Перейти к SRC/Компоненты/Header.js Файл и добавить выше вернуть утверждение:
console.log("Header is running")
В SRC/Компоненты/inputtodo.js Файл, добавьте это также:
console.log("InputTodo is running", addTodoItem)
В SRC/Компоненты/ToDoslist.js , Добавь это:
console.log("TodosList is running", value)
И, наконец, в Todoitem.js Файл, добавьте журнал.
...
return (
{(value) => {
const { handleChange, delTodo } = value;
console.log("TodoItem is running", handleChange, delTodo);
return (
...
);
}}
);
...
Сохраните все свои файлы и посмотрите на консоль вашего браузера devtools.
Как видно выше,
На странице нагрузки все компоненты рендурируют и как таковые отображают их соответствующие сообщения журнала в консоли (как выделено в красной границе на изображении выше).
Если вы нажмете любой флажок, удалите кнопку «Удалить или отправить», все компоненты, потребляющие данные контекста, будут восстановлены (как выделено в черной границе). Даже когда эти отдельные элементы получают доступ к части данных.
Это опасность прохождения объектов к контексту ценность как против простой строки или номера. Простое обновление, которое влияет на только часть объекта, приведет к переизложению бесчисленных компонентов.
С изображения выше, вы можете увидеть TodoContainer и Заголовок Компоненты не рендурируют после нагрузки на начальную страницу. Это потому, что они не употребляют контекстные данные.
Теперь, давайте попробуем что-нибудь написать в поле ввода текста, пока открывается консоль.
На каждом нажатии клавиши только Inputtodo.js оказывается.
Это происходит потому, что Onchange Функция (которая отвечает за эти изменения через локальную переменную государства) в этом компоненте не является частью контекста.
Представь, ты берешь это Onchange Функция и локальное состояние в контекст ценность пропры Как вы думаете, что случится?
На каждом нажатии клавиши все компоненты, потребляющие данные контекста, будут повторно рендерировать. Это не идеально, так как это может вызвать выпуск производительности.
Точка, чтобы отметить здесь:
Не все данные состояния в вашем приложении должны быть доступны во всем мире (то есть в контексте). Держите местное состояние, где это нужно.
От того, что мы видели до сих пор,
Контекст не может быть практически подходит для приложения с частотенными изменениями состояния, если вы хотите легко избежать проблемой ненужных компонентов повторного рендеринга.
Хотя мы можем управлять этой проблемой, расщепляя контекст на кратные. Но в этом случае разная часть контекстных данных должна быть в состоянии обновлять независимо.
Вывод
Пока вы узнали, как использовать API контекста в вашем приложении React, независимо от типов компонентов, вы также видели общие подводные камни, которые поставляются с этим API.
Хотя многие разработчики согласны с тем, что безопасно использовать даже в нашем сложном приложении, если мы не видим проблем с производительностью. Но мы не можем упускать из виду бесчисленные повторные рендеры в наших компонентах.
Сказав это, я предложу вам только для контекста API только в том случае, если ваши государственные данные требуют более низких частотных обновлений, и когда вы обнаружите, что опорное бурение становится проблемой – то есть, когда вы передаваете разрыву во многие глубоко вложенные компоненты.
Не просто используйте его просто потому, что вы хотите избежать бурения оперирования (если это очень возможно).
Теперь ваш черед!
У вас есть вопросы, трудности или взносы в отношении этой темы? Пожалуйста, дайте мне знать через раздел комментариев.
Если вам понравится этот контекстный учебный пособие, стремиться поделиться этим постом по Интернету и убедиться, что вы следите за мной на Twitter получить больше обновлений.
Twitter: @ibaslogic Отказ
Исходный код проекта на github.
Оригинал: “https://dev.to/ibaslogic/react-context-api-made-simple-the-practical-guide-5239”