Эта статья участвовала в приказе о созыве Haowen, нажмите, чтобы просмотреть:Двойные заявки на внутреннюю и внешнюю стороны, призовой фонд в 20 000 юаней ждет вас, чтобы бросить вызов!
В этой серии будет описано, как использовать React Hooks, начиная с useState, и будет рассмотрено следующее:
Освоение API React Hooks поможет вам лучше использовать его в своей работе, а ваше владение React перейдет на новый уровень. В этой серии будет использоваться много примеров кода и демонстраций эффектов, которые очень просты в использовании для новичков и рецензентов.
Сегодня мы поговорим об использовании объекта Context и useContext.
Что такое контекстные API
Рассмотрим такой сценарий, если древовидная структура компонентов следующая, и теперь вы хотите передать атрибут userName из корневого узла в листовой узел ADF, и передать его через props, он неизбежно пройдет через BCE, даже если эти компоненты не используйте этот атрибут userName.
Если такая вложенная древовидная структура имеет 5 или 10 уровней, это будет катастрофический опыт разработки и обслуживания. Этой проблемы можно избежать, если вы можете перейти сразу в нужное вам место, не проходя через промежуточные узлы, тогда Context api здесь для решения этой проблемы.
Контекстный API — это API, который передает данные в дереве компонентов, не проходя через каждый уровень. Давайте посмотрим на использование Context Hook.
использовать контекст
Давайте возьмем пример, чтобы сосредоточиться на самой правой ветви, C E F, передавая переменное имя пользователя из корневого узла в узел F.
Сначала мы создаем App, ComponentC, ComponentE, ComponentF следующим образом.
App.tsx
import React from 'react'
import './App.css'
import ComponentC from './components/16ComponentC'
const App = () => {
return (
<div className="App">
<ComponentC />
</div>
)
}
export default App
ComponentC.tsx
import React from 'react'
import ComponentE from './16ComponentE'
function ComponentC() {
return (
<div>
<ComponentE />
</div>
)
}
export default ComponentC
ComponentE.tsx
import React from 'react'
import ComponentF from './16ComponentF'
function ComponentE() {
return (
<div>
<ComponentF />
</div>
)
}
export default ComponentE
ComponentF.tsx
import React from 'react'
function ComponentF() {
return (
<div>
ComponentF
</div>
)
}
export default ComponentF
Страница выглядит следующим образом:
Далее давайте изучим, как использовать Context для передачи имени пользователя из приложения в ComponentF, который разделен на следующие 3 шага.
создать контекст
Использовать в корневом узле App.tsxcreateContext()
создать контекст
const UserContext = React.createContext('')
Создайте объект контекста. Когда React отображает компонент, который подписывается на этот объект Context, компонент будет считывать текущее значение контекста из соответствующего Provider, ближайшего к нему в дереве компонентов.
Параметр defaultValue вступит в силу только в том случае, если в дереве, где находится компонент, нет соответствующего поставщика. Это помогает тестировать компоненты, не оборачивая их в Provider. Примечание. Когда в значение поставщика передается значение undefined, значение defaultValue компонента-потребителя не вступает в силу.
Провайдер
Используйте Provider в корневом узле, чтобы обернуть дочерние узлы и предоставить контекст дочерним узлам.
<UserContext.Provider value={'chuanshi'}>
<ComponentC />
</UserContext.Provider>
Каждый объект Context возвращает компонент Provider React, который позволяет потребляющим компонентам подписываться на изменения контекста.
Провайдер получает
value
свойство, передаваемое потребляющему компоненту. Поставщик может иметь соответствующие отношения с несколькими потребительскими компонентами. Несколько провайдеров также могут быть вложены друг в друга, и внутренний уровень будет охватывать данные внешнего уровня.Когда у провайдера
value
Когда значение изменяется, все потребляющие компоненты внутри него перерисовываются. Ни Провайдер, ни его внутренние потребительские компоненты не подлежатshouldComponentUpdate
функция, так что компонент-потребитель может обновляться, даже если его компонент-предок выходит из обновления.Изменения определяются путем проверки старых и новых значений по тому же алгоритму, что и Object.is.
Не забудьте экспортировать ранее определенный Контекст, чтобы его можно было ввести в узлы-потомки.
export const UserContext = React.createContext('')
На данный момент полный код App.tsx
import React from 'react'
import './App.css'
import ComponentC from './components/16ComponentC'
export const UserContext = React.createContext('')
const App = () => {
return (
<div className="App">
<UserContext.Provider value={'chuanshi'}>
<ComponentC />
</UserContext.Provider>
</div>
)
}
export default App
Потребляйте контекст в используемом узле
импортировать объект контекста
import { UserContext } from '../App'
Потребляйте вместе с потребителем
<UserContext.Consumer>
{
(user) => (
<div>
User context value {user}
</div>
)
}
</UserContext.Consumer>
Здесь компоненты React также могут подписываться на изменения контекста. Это позволяет вам подписываться на контексты в функциональных компонентах.
Это требует практики функции как ребенок. Эта функция принимает текущее значение контекста и возвращает NoDe odd. Значение, передаваемое на функцию, эквивалентно значению, предоставляемую поставщику, ближайшим к контексту вверх по дерево компонента. Если нет соответствующего провайдера, параметр значения эквивалентен по умолчанию значение для CreateContext ().
Полный код ComponentF.tsx выглядит следующим образом.
import React from 'react'
import { UserContext } from '../App'
function ComponentF() {
return (
<div>
<UserContext.Consumer>
{
(user) => (
<div>
User context value {user}
</div>
)
}
</UserContext.Consumer>
</div>
)
}
export default ComponentF
Эффект следующий
В настоящее время ситуация хороша, когда есть только один Контекст.Давайте посмотрим на ситуацию с несколькими Контекстами.
Несколько контекстных ситуаций
Добавляем еще один Context в App.tsx
import React from 'react'
import './App.css'
import ComponentC from './components/16ComponentC'
export const UserContext = React.createContext('')
export const ChannelContext = React.createContext('')
const App = () => {
return (
<div className="App">
<UserContext.Provider value={'chuanshi'}>
<ChannelContext.Provider value={'code volution'}>
<ComponentC />
</ChannelContext.Provider>
</UserContext.Provider>
</div>
)
}
export default App
Затем потребляйте их в компоненте F
import React from 'react'
import { UserContext, ChannelContext } from '../App'
function ComponentF() {
return (
<div>
<UserContext.Consumer>
{
(user) => (
<ChannelContext.Consumer>
{
(channel) => (
<div>
User context value {user}, channel value {channel}
</div>
)
}
</ChannelContext.Consumer>
)
}
</UserContext.Consumer>
</div>
)
}
export default ComponentF
Страница отображается следующим образом
Хотя код работает без проблем, но внешний вид и читабельность не очень хороши, если несколько контекстов, есть лучший способ — использовать хук контекста, чтобы решить проблему более элегантного кода, чем потребление контекста.
useContext
Например, мы передаем компонент E в приведенной выше демонстрации.useContext
Используйте контекст, созданный корневым узлом. в следующие шаги
- импорт из реагирующего объекта
useContext
этот хук API - импортировать объект Context, созданный корневым узлом (можно импортировать несколько)
- воплощать в жизнь
useContext()
метод, проходящий в контексте
Полный код ComponentE:
import React, { useContext } from 'react'
import ComponentF from './16ComponentF'
import {UserContext, ChannelContext} from '../App'
function ComponentE() {
const user = useContext(UserContext)
const channel = useContext(ChannelContext)
return (
<div>
<ComponentF />
--- <br/>
{user} - {channel}
</div>
)
}
export default ComponentE
Страница отображается следующим образом
Ключевая строка кода выглядит следующим образом
const value = useContext(MyContext)
Метод useContext принимает объект контекста (
React.createContext
возвращаемое значение) и возвращает текущее значение этого контекста. Текущее значение контекста определяется ближайшим компонентом верхнего компонента к текущему компоненту.<MyContext.Provider>
изvalue
опорное решение.Когда самый верхний компонент компонента является ближайшим
<MyContext.Provider>
При обновлении этот хук вызывает повторный рендеринг с последним переданнымMyContext
контекст провайдераvalue
стоимость. даже если предки используютReact.memo
илиshouldComponentUpdate
, также используется в самом компонентеuseContext
повторно рендерить.можно понимать как,
useContext(MyContext)
Эквивалент компонента класса вstatic contextType = MyContext
или<MyContext.Consumer>
.
useContext(MyContext)
Просто позволяет читать значение контекста и подписываться на изменения в контексте. Вам все еще нужно использовать в верхнем дереве компонентов<MyContext.Provider>
для обеспечения контекста для базовых компонентов.
На данный момент мы освоили использование API-интерфейса useContext и видим, что использование useContext может значительно снизить сложность кода, используемого несколькими контекстами.
В следующей главе мы поговорим об использовании useReducer.