Старый контекст
Примечание:
API старого контекста будет удален в будущей основной версии. Используйте новый API контекста, представленный в версии 16.3. Старый API будет продолжать работать для всех релизов 16.x.
Как использовать контекст
Этот раздел описывает устаревший API. См. новый API.
Предположим, у вас есть структура, подобная:
class Button extends React.Component {
render() {
return (
<button style={{background: this.props.color}}>
{this.props.children}
</button>
);
}
}
class Message extends React.Component {
render() {
return (
<div>
{this.props.text} <Button color={this.props.color}>Delete</Button>
</div>
);
}
}
class MessageList extends React.Component {
render() {
const color = "purple";
const children = this.props.messages.map((message) =>
<Message text={message.text} color={color} />
);
return <div>{children}</div>;
}
}В этом примере мы вручную передаём color prop для соответствующей стилизации компонентов Button и Message. С помощью контекста мы можем автоматически передать эту информацию по дереву:
import PropTypes from 'prop-types';
class Button extends React.Component {
render() {
return (
<button style={{background: this.context.color}}>
{this.props.children}
</button>
);
}
}
Button.contextTypes = {
color: PropTypes.string
};
class Message extends React.Component {
render() {
return (
<div>
{this.props.text} <Button>Delete</Button>
</div>
);
}
}
class MessageList extends React.Component {
getChildContext() {
return {color: "purple"};
}
render() {
const children = this.props.messages.map((message) =>
<Message text={message.text} />
);
return <div>{children}</div>;
}
}
MessageList.childContextTypes = {
color: PropTypes.string
};
Добавив childContextTypes и getChildContext в MessageList (поставщик контекста), React автоматически передаёт информацию вниз, и любой компонент в поддереве (в данном случае, Button) может получить к ней доступ, определив contextTypes.
Если contextTypes не определён, то context будет пустым объектом.
Примечание:
React.PropTypesпереместился в другой пакет с React v15.5. Пожалуйста, используйте библиотекуprop-typesдля определенияcontextTypes.Мы предоставляем скрипт codemod для автоматизации преобразования.
Связывание родительских и дочерних компонентов
Этот раздел описывает устаревший API. См. новый API.
Контекст также позволяет создавать API, где родители и дети взаимодействуют. Например, одна библиотека, которая работает таким образом, это React Router V4:
import { BrowserRouter as Router, Route, Link } from 'react-router-dom';
const BasicExample = () => (
<Router>
<div>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/about">About</Link></li>
<li><Link to="/topics">Topics</Link></li>
</ul>
<hr />
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/topics" component={Topics} />
</div>
</Router>
);Передавая информацию из компонента Router, каждый компонент Link и Route может общаться с содержащим его компонентом Router.
Прежде чем создавать компоненты с API, аналогичным этому, подумайте о более чистых альтернативах. Например, вы можете передавать целые компоненты React в качестве props, если хотите.
Обращение к контексту в методах жизненного цикла
Этот раздел описывает устаревший API. См. новый API.
Если contextTypes определён внутри компонента, следующие методы жизненного цикла получат дополнительный параметр — объект context.
constructor(props, context)componentWillReceiveProps(nextProps, nextContext)shouldComponentUpdate(nextProps, nextState, nextContext)componentWillUpdate(nextProps, nextState, nextContext)
Примечание:
Начиная с React 16,
componentDidUpdateбольше не получаетprevContext.
Обращение к контексту в бесклассовых функциональных компонентах
Этот раздел описывает устаревший API. См. новый API.
Функциональные компоненты также могут обращаться к context, если contextTypes определён как свойство функции. Следующий код демонстрирует компонент Button, написанный как функциональный компонент.
import PropTypes from 'prop-types';
const Button = ({children}, context) =>
<button style={{background: context.color}}>
{children}
</button>;
Button.contextTypes = {color: PropTypes.string};Обновление контекста
Этот раздел описывает устаревший API. См. новый API.
Не делайте этого.
React имеет API для обновления контекста, но он фундаментально неисправен, и его не следует использовать.
Функция getChildContext вызывается при изменении состояния или свойств. Чтобы обновить данные в контексте, вызовите локальное обновление состояния с помощью this.setState. Это вызовет новый контекст, и изменения будут получены потомками.
import PropTypes from 'prop-types';
class MediaQuery extends React.Component {
constructor(props) {
super(props);
this.state = {type:'desktop'};
}
getChildContext() {
return {type: this.state.type};
}
componentDidMount() {
const checkMediaQuery = () => {
const type = window.matchMedia("(min-width: 1025px)").matches ? 'desktop' : 'mobile';
if (type !== this.state.type) {
this.setState({type});
}
};
window.addEventListener('resize', checkMediaQuery);
checkMediaQuery();
}
render() {
return this.props.children;
}
}
MediaQuery.childContextTypes = {
type: PropTypes.string
};Проблема заключается в том, что если значение контекста, предоставленное компонентом, меняется, потомки, которые используют это значение, не обновятся, если промежуточный родитель вернёт false из shouldComponentUpdate. Это полностью вне контроля компонентов, использующих контекст, поэтому, по сути, нет надёжного способа обновить контекст. В этом блоге есть хорошее объяснение, почему это проблема, и как её можно обойти.
© 2013–present Facebook Inc.
Licensed under the Creative Commons Attribution 4.0 International Public License.
https://17.reactjs.org/docs/legacy-context.html