ݺߣ

ݺߣShare a Scribd company logo
Контекст в React
Николай Надоричев
Frontend-разработчик
Сбербанк Технологии
31
• Проблемы коммуникации компонентов
• Строим своё дерево компонентов
• Пишим свой flux
Коммуникация компонентов
• От родителя в ребенку
Parent
Child
Props
Коммуникация компонентов
• От ребенка к родителю
Parent
Child
Callbacks
Child
Child
Child
Коммуникация компонентов
• От родителя к детям в глубине DOM-
дерева
Parent
Child
???
RadioButtonGroup
RadioButtonGroup
<RadioGroup onChange={(value) => alert(value)}>

<RadioButton value="1">Опция 1</
RadioButton>

<RadioButton value="2">Опция 2</
RadioButton>

<RadioButton value="3">Опция 3</
RadioButton>

</RadioGroup>
RadioButtonGroup
class RadioButtonGroup extends React.Component {

. . .

childClick() { … }



render() {

return <div>

{this.props.children.map((Radio, index) => {

return React.cloneElement(Radio, {

onChange: () => this.childClick(value), 

selected: this.state.value === Radio.props.value,

key: index})

})}

</div>;

}

}
RadioButtonGroup
class RadioButtonGroup extends React.Component {

. . .

childClick() { … }



render() {

return <div>

{this.props.children.map((Radio, index) => {

return React.cloneElement(Radio, {

onChange: () => this.childClick(value), 

selected: this.state.value ===
Radio.props.value,

key: index})

})}

</div>;

}

RadioButtonGroup
class RadioButtonGroup extends React.Component {

. . .

childClick() { … }



render() {

return <div>

{this.props.children.map((Radio, index) => {

return React.cloneElement(Radio, {

onChange: () => this.childClick(value), 

selected: this.state.value === Radio.props.value,

key: index})

})}

</div>;

}

}
RadioButtonGroup
<RadioGroup onChange={(value) => alert(value)}>

<h1>Выберите опцию</h1>

<div><RadioButton value="1">Опция 1</
RadioButton></div>

<div><RadioButton value="2">Опция 2</
RadioButton></div>

<div><RadioButton value="3">Опция 3</
RadioButton></div>

</RadioGroup>
Child
Child
Child
Коммуникация компонентов
• От родителя к детям в глубине DOM-
дерева
Parent
Child
Contex
t
Context
• Передает через специальный аргумент
параметры всем дочерним элементам
• Пробрасывается, если дочерний
элемент запросил параметр явно
RadioButtonGroup
class RadioButtonGroup extends React.Component {

getChildContext() {

return {

onRadioChange: () => this.childClick(value),

radioValue: this.state.value

}

}

}
RadioButtonGroup.childContextTypes = {

onRadioChange: React.PropTypes.func,

radioValue: React.PropTypes.string

}
RadioButtonGroup
class RadioButtonGroup extends React.Component {

getChildContext() {

return {

onRadioChange: () => this.childClick(value),

radioValue: this.state.value

}

}

}
RadioButtonGroup.childContextTypes = {

onRadioChange: React.PropTypes.func,

radioValue: React.PropTypes.string

}
RadioButton
class RadioButton extends React.Component {

render() {

return <div

className={this.context.selected ? 'radio-active' : 'radio-
inactive'}

onClick={() => this.context.onRadioChange(this.props.value)}>

{this.props.children}

</div>;

}

}



RadioButton.contextTypes = {

onRadioChange: React.PropTypes.func,

radioValue: React.PropTypes.string

};
RadioButton
class RadioButton extends React.Component {

render() {

return <div

className={this.context.selected ? 'radio-active' : 'radio-
inactive'}

onClick={() => this.context.onRadioChange(this.props.value)}>

{this.props.children}

</div>;

}

}



RadioButton.contextTypes = {

onRadioChange: React.PropTypes.func,

radioValue: React.PropTypes.string

};
RadioButton
class RadioButton extends React.Component {

render() {

return <div

className={this.context.selected ? 'radio-active' : 'radio-
inactive'}

onClick={() => this.context.onRadioChange(this.props.value)}>

{this.props.children}

</div>;

}

}



RadioButton.contextTypes = {

onRadioChange: React.PropTypes.func,

radioValue: React.PropTypes.string

};
RadioButton
class RadioButton extends React.Component {

render() {

return <div

className={this.context.selected ? 'radio-active' : 'radio-
inactive'}

onClick={() => this.context.onRadioChange(this.props.value)}>

{this.props.children}

</div>;

}

}



RadioButton.contextTypes = {

onRadioChange: React.PropTypes.func,

radioValue: React.PropTypes.string

};
Component.contextTypes = {

property: React.PropTypes.any

};



Component.childContextTypes = {

property: React.PropTypes.any

};
Дерево оберток
class Leaf extends React.Component {

childLeaves = [];



getChildContext() {

return {

mountLeaf: (instance) => this.childLeaves.push(instance)

}

};



componentDidMount() {

this.context.mountLeaf(this);

}

}



Leaf.contextTypes = {

mountLeaf: React.PropTypes.func

};



Leaf.childContextTypes = {

mountLeaf: React.PropTypes.func

};
Дерево оберток
Wrapper
Wrapper
Wrapper Wrapper
Wrapper
Wrapper
Дерево оберток
Дерево оберток
Давайте напишем свой flux
WAT?!
Flux через context
FluxContainer
constructor() {

super(...arguments);



this.state = {

store: this.props.initialStore

}

}
FluxContainer
dispatchAction(action, params) {

let store = this.state.store;

this.props.actions[action](store, params);

this.setState({store});

}
FluxWrapper
return React.cloneElement(

React.Children.only(this.props.children),

{

dispatch: (action, params) =>
this.context.dispatchAction(action, params),

store

}

);
App
Flux через context
FluxContainte
r
FluxWrapper
Component
initialStore
actions
dispatch
store
dispatch
store
Flux через context
http://bit.ly/MJS31-flux
Context в СберТехе
• AppContainer
• SpringWebFlowRouter
• Focusable
Спасибо! Вопросы?
Надоричев Николай
Сбербанк Технологии
@luanre
@luanre
email: luanre@gmail.com
http://bit.ly/MJS31-flux
Demo flux:
RadioButtonGroup
class RadioButtonGroup extends React.Component {

. . .

childClick() { … }



render() {

return <div>

{this.props.children.map((Radio, index) => {

return React.cloneElement(Radio, {

onChange: () => this.childClick(value), 

selected: this.state.value === Radio.props.value,

key: index})

})}

</div>;

}

}
RadioButtonGroup
class RadioButtonGroup extends React.Component {

getChildContext() {

return {

onRadioChange: () => this.childClick(value),

radioValue: this.state.value

}

}

}
RadioButtonGroup.childContextTypes = {

onRadioChange: React.PropTypes.func,

radioValue: React.PropTypes.string

}
RadioButton
class RadioButton extends React.Component {

render() {

return <div

className={this.context.selected ? 'radio-active' : 'radio-
inactive'}

onClick={() => this.context.onRadioChange(this.props.value)}>

{this.props.children}

</div>;

}

}



RadioButton.contextTypes = {

onRadioChange: React.PropTypes.func,

radioValue: React.PropTypes.string

};

More Related Content

Контекст в React, Николай Надоричев, MoscowJS 31