React - это библиотека для создания интерфейсных представлений. Он имеет большую экосистему библиотек, которые с ним работают. Кроме того, мы можем использовать его для улучшения существующих приложений.
Компоненты React могут передавать данные от родителя к потомку только через props. Контекстный API дополняет это, позволяя компонентам с другими отношениями обмениваться данными.
В этой статье мы рассмотрим, как использовать его для обмена данными между компонентами.
Когда использовать контекст
Мы должны использовать Context для обмена данными между компонентами React. Однако его следует использовать с осторожностью, поскольку он создает тесную связь между компонентами.
Чтобы использовать его в простом приложении, мы можем написать следующее:
const ColorContext = React.createContext("green"); class Button extends React.Component { render() { return ( <div> <ColorContext.Consumer> {value => ( <button style={{ color: value }}>{this.props.children}</button> )} </ColorContext.Consumer> </div> ); } } class App extends React.Component { render() { return ( <div> <ColorContext.Provider value="blue"> <Button>Click Me</Button> </ColorContext.Provider> </div> ); } }
В приведенном выше коде мы создали контекст для обмена данными, написав:
const ColorContext = React.createContext("green");
createContext
принимает значение по умолчанию в качестве аргумента, где мы передали 'green'
.
Затем в компоненте App
у нас есть компонент ColorContext.Provider
с параметром value
, установленным на значение, которым мы хотим поделиться.
В приведенном выше примере это будет 'blue'
. Мы обернули его вокруг компонентов, с которыми мы хотим поделиться данными, чтобы мы могли получить доступ к значению из этого компонента.
В этом случае мы создали новый компонент Button
, который имеет компонент ColorContext.Consumer
. Внутри него мы можем получить значение, предоставленное поставщиком контекста, из параметра value
в функции, которую мы вставили в компонент ColorContext.Consumer
.
value
должен быть установлен в 'blue'
, поскольку это то, что мы установили в качестве значения value
prop.
Внутри функции, которую мы передали потребителю, мы вернули элемент buttom
с опорой стиля и установили стиль color
на value
, то есть 'blue'
.
Альтернативы контексту
Если мы хотим передать данные глубоко вложенному компоненту, мы можем вместо этого передать весь компонент туда, где мы хотим. Таким образом, нам не нужно беспокоиться о передаче свойств на несколько уровней, чтобы передать то, что нужно только глубоко вложенным компонентам.
Например, если мы хотим передать свойство цвета Button
компонентам, которое содержится в ButtonBar
. Мы можем сделать это следующим образом:
class Button extends React.Component { render() { return ( <button style={{ color: this.props.color }}>{this.props.children}</button> ); } } class ButtonBar extends React.Component { render() { return this.props.buttons; } } class App extends React.Component { render() { const buttons = [ <Button color="blue">Click Me</Button>, <Button color="green">Click Me 2</Button> ]; return <ButtonBar buttons={buttons} />; } }
В компоненте App
у нас есть компоненты Button
в массиве buttons
. Затем мы передали весь массив прямо в компонент ButtonBar
.
Затем ButtonBar
просто возвращает то, что мы передали, то есть this.props.buttons
.
Это также означает большую сложность компонентов более высокого порядка, поэтому это может не подходить во всех случаях.
Обновление контекста из вложенного компонента
Мы можем передавать функции объекту, который мы передаем в createContext
, чтобы мы могли вызывать их внутри компонента, который имеет компонент-потребитель контекста.
Например, мы можем написать следующее:
const colorObj = { color: "green", toggleColor: () => {} }; const ColorContext = React.createContext(colorObj); class Button extends React.Component { render() { return ( <div> <ColorContext.Consumer> {({ color, toggleColor }) => ( <button onClick={toggleColor} style={{ color }}> {this.props.children} </button> )} </ColorContext.Consumer> </div> ); } } class App extends React.Component { constructor(props) { super(props); this.state = { color: "blue", toggleColor: () => { this.setState(state => ({ color: state.color === "green" ? "blue" : "green" })); } }; } render() { return ( <div> <ColorContext.Provider value={this.state}> <Button>Click Me</Button> </ColorContext.Provider> </div> ); } }
Приведенный выше код начинается с определения объекта colorObj
, который передается в createContext
как значение по умолчанию ColorContext
.
Затем в компоненте App
мы инициализируем this.state
, устанавливая его для объекта с функцией toggleColor
, а для свойства color
установлено значение 'blue'
.
Мы передаем this.state
как значение свойства value
для ColorContext.Provider
.
Затем мы получаем доступ ко всему объекту внутри компонента ColorContext.Consumer
в компоненте Button
.
Внутри мы получаем свойства color
и toggleColor
из this.state
, которые мы передали из ColorContext.Provider
. Затем мы передаем toggleColor
в свойство onClick
и color
в объект, который мы передали в свойство style
.
Затем, когда мы нажимаем кнопку Click Me, цвет текста будет переключаться между синим и зеленым.
Использование нескольких контекстов
Мы можем использовать несколько контекстов, вложив их. Например, мы можем сделать это следующим образом:
const ColorContext = React.createContext("green"); const BorderContext = React.createContext(""); class Button extends React.Component { render() { return ( <div> <ColorContext.Consumer> {color => ( <BorderContext.Consumer> {border => ( <button style={{ color, border }}>{this.props.children}</button> )} </BorderContext.Consumer> )} </ColorContext.Consumer> </div> ); } } class App extends React.Component { render() { return ( <div> <ColorContext.Provider value="blue"> <BorderContext.Provider value="3px solid green"> <Button>Click Me</Button> </BorderContext.Provider> </ColorContext.Provider> </div> ); } }
В приведенном выше коде мы создаем 2 контекста, ColorContext
и BorderContext
и передаем значения в опору value
для обоих. Мы вложили поставщиков в компонент App
, что означает, что оба контекста могут использоваться компонентом Button
внутри.
Затем в компоненте Button
у нас есть потребители для обоих контекстов, вложенных друг в друга. И тогда мы можем получить оба значения, которые были переданы от провайдеров.
Затем мы используем оба значения для установки стилей button
.
В итоге мы получили кнопку с синим текстом и толстой зеленой рамкой.
Заключение
Мы можем использовать React Context API для обмена данными между компонентами.
Он работает путем создания объекта Context с React.createContext
. Затем мы оборачиваем компонент поставщика контекста за пределы компонентов, из которых мы хотим использовать контекст.
Затем в компоненте, который мы помещаем в поставщик, у нас есть компонент-потребитель контекста, обернутый вне того, к чему мы хотим применить значение контекста.
Наконец, мы можем получить значение внутри функции, которую мы передаем внутри потребителя контекста.