[Перевод] Вышел React v.16.3.0
Несколько дней назад, мы написали пост о приближающихся изменениях в наших lifecycle-методах, где также затронули стратегию постепенной миграции (обновления). В React 16.3.0 мы добавили несколько новых lifecycle-методов для помощи в этой миграции. Мы также предоставили новое API для давно ожидаемых новшеств: официальное context API, ref forwarding API и ergonomic ref API.
Официальное Context API
Много лет React предлагал экспериментальное API для работы с контекстом. Пусть это и была мощная «штука», использование такого API было под угрозой, так как мы всё хотели заменить «экспериментальное» API.
Версия 16.3 представляет новое context API, которое эффективнее и поддерживает сразу как проверку статичных типов (static type checking) так и глубокие обновления (deep updates).
Старое context API будет работать для всех релизов 16й версии, поэтому у вас есть время мигрировать.
Ниже пример, в котором показано как можно «прокинуть» тему оформления (theme), используя новое API:
const ThemeContext = React.createContext('light');
class ThemeProvider extends React.Component {
state = {theme: 'light'};
render() {
return (
{this.props.children}
);
}
}
class ThemedButton extends React.Component {
render() {
return (
{theme => }
);
}
}
Больше о context API здесь.
createRef API
React предоставлял два способа управления refs: указание ref обычной строкой и callback-вызов. Хотя и указание ref просто в качестве строки было удобнее, это имело несколько минусов и поэтому мы рекомендовали использовать вариант с callback’ом.
Версия 16.3 добавляет новую опцию для управления refs, которая предлагает удобство указания ref в виде строки без недочетов:
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.inputRef = React.createRef();
}
render() {
return ;
}
componentDidMount() {
this.inputRef.current.focus();
}
}
Callback refs будут поддерживаться и далее в новом createRef API. Не спешите заменять callback refs в ваших компонентах. Они более гибкие, поэтому мы оставим их для будущего продвинутого использования.
Больше о createRef API здесь.
forwardRef API
Компоненты высшего порядка (или HOC) — удобный инструмент для «переиспользования» кода между компонентами. Если взять за основу предыдущий пример с context, мы можем создать HOC в который «прокинем» theme в качестве свойства (props):
function withTheme(Component) {
return function ThemedComponent(props) {
return (
{theme => }
);
};
}
Мы можем использовать этот HOC, чтобы связывать компоненты со свойствами темы оформления (theme) из контекста (context) без использования ThemeContext напрямую. Для примера:
class FancyButton extends React.Component {
buttonRef = React.createRef();
focus() {
this.buttonRef.current.focus();
}
render() {
const {label, theme, ...rest} = this.props;
return (
);
}
}
const FancyThemedButton = withTheme(FancyButton);
// Мы можем отрисовать FancyThemedButton, как будто это FancyButton
// Компонент автоматически получит текущую тему (*свойство theme*)
// И HOC прокинет его вниз через props.
;
Обычно HOC’и прокидывают свойства (props) в компонент, который они оборачивают. К сожалению, refs не прокидываются. Это значит, что мы не можем прикрепить ref к FancyButton когда используем FancyThemedButton. Выходит, вызвать focus()
невозможно.
forwardRef API решает эту проблему, предлагая перехватить ref и послать его дальше как обычное свойство.
function withTheme(Component) {
// обратите внимание, что "ref" предоставлен нам React.forwardRef.
function ThemedComponent(props, ref) {
return (
{theme => (
)}
);
}
// Следующие несколько строк кода необязательны,
// они нужны чтобы дать компоненту понятное имя в DevTools,
// например, "ForwardRef(withTheme(MyComponent))"
const name = Component.displayName || Component.name;
ThemedComponent.displayName = `withTheme(${name})`;
// Просим React прокинуть ref в ThemedComponent.
return React.forwardRef(ThemedComponent);
}
const fancyButtonRef = React.createRef();
// Сейчас fancyButtonRef указывает на FancyButton
;
Изменения в методах жизненного цикла (lifecycle methods)
API создания компонентов с помощью class практически не изменялось несколько лет. Однако, мы добавили поддержку новых «фич» (таких как error boundaries или будущий async rendering mode) к которым данная модель была не готова как следует.
Например, с текущим API очень просто заблокировать начальную отрисовку компонента (initial render) несущественной логикой. Отчасти, это связано с тем, что существует несколько вариантов для решения поставленных задач, и поэтому выбрать лучший не просто. Мы заметили, что обработке ошибок часто не уделяется внимание и это может приводить к утечкам памяти (что в свою очередь пагубно скажется в будущем на асинхронной отрисовке (async rendering mode)). Текущее class API так же осложняет другие наши задумки, например работу над прототпированием React компилятора.
Большинство из таких проблем связано со следующими lifecycle-методами: componentWillMount, componentWillUnmount и ComponentWillUpdate. Так же эти методы вносят наибольшую путаницу в React коммьюнити. Поэтому, мы собираемся отказаться них в пользу лучшей альтернативы.
Конечно, мы понимаем, что такие изменения затронут огромное количество существующих компонентов. Поэтому миграция будет постепенной настолько, насколько это возможно. Мы также предложим пути отступления (У нас в Facebook — 50,000 компонентов. Мы так же нуждаемся в постепенном обновлении).
Deprecation (устаревший метод) предупреждение будет включено в будущих 16.x релизах, но поддержка текущих «жизненных циклов» будет работать до версии 17. Так же, в семнадцатой версии вы сможете использовать их с префиксом UNSAFE_. Мы приготовили автоматический скрипт для переименования.
В дополнении к будущим «deprecated» методам жизненного цикла, мы добавили парочку новых:
- getDerivedStateFromProps — альтернатива для componentWillReceiveProps
- getSnapshotBeforeUpdate — альтернатива для безопасного чтения свойств из DOM, прежде чем случится обновление.
Больше об изменении в lifecycle здесь.
StrictMode компонент
StrictMode — это инструмент для нахождения потенциальных проблем в вашем приложении. Как и Fragment, StrictMode визуально не отрисовывается. Этот компонент активирует дополнительные проверки и предупреждения.
StrictMode работает только в development режиме (в режиме разработки, не в «проде»)
Несмотря на то, что невозможно поймать все проблемные места (например, некоторые типы мутаций), StrictMode компонент поможет во многих ситуациях. Если вы видите предупреждения в «строгом режиме» (strict mode), значит скорее всего у вас будут баги в асинхронном режиме отрисовки (async rendering mode).
В версии 16.3, StrictMode умеет:
- находить компоненты, использующие небезопасные (старые) lifecycle-методы
- предупреждать об использовании старого API обозначения ref как строки
- выслеживать непредвиденные side-эффекты
Дополнительный функционал будет добавлен в будущих релизах React.
Больше о StrictMode здесь.