React v16.3.0: новые методы жизненного цикла и API контекста
29 Марта, 2018. Brian Vaughn (Брайан Вон)
Недавно мы написали о предстоящем внесении изменений в наши методы жизненного цикла,
включая стратегии постепенной миграции. В React 16.3.0 мы добавляем несколько новых
методов жизненного цикла, чтобы помочь с этой миграцией. Также мы внедряем новые API
для давно ожидаемых функций: официальный API для контекста, API для передачи ссылки
ref
и эргономичный API для ref
.
Недавно мы написали о предстоящем внесении изменений в наши методы жизненного цикла,
включая стратегии постепенной миграции. В React 16.3.0 мы добавляем несколько новых
методов жизненного цикла, чтобы помочь с этой миграцией. Также мы внедряем новые API
для давно ожидаемых функций: официальный API для контекста, API для передачи ссылки
ref
и эргономичный API для ref
.
Читайте дальше, чтобы узнать больше о релизе.
Официальный API контекста
В версии 16.3 представлен новый API контекста, который более эффективен и поддерживает как статическую проверку типа, так и глубокие обновления.
В течение многих лет React предлагал экспериментальный API для контекста. Хотя это был мощный инструмент, его использование было обескуражено из-за присущих ему проблем с API. Мы всегда собирались заменить экспериментальный API на лучший.
В версии 16.3 представлен новый API контекста, который более эффективен и поддерживает как статическую проверку типа, так и глубокие обновления.
Внимание!
Старый API контекста будет работать для всех релизов React 16.x, поэтому у вас будет время для миграции.Вот пример, иллюстрирующий, как вы можете вводить «тему» с использованием нового API контекста:
const ThemeContext = React.createContext('light');
class ThemeProvider extends React.Component {
state = {theme: 'light'};
render() {
return (
<ThemeContext.Provider value={this.state.theme}>
{this.props.children}
</ThemeContext.Provider>
);
}
}
class ThemedButton extends React.Component {
render() {
return (
<ThemeContext.Consumer>
{theme => <Button theme={theme} />}
</ThemeContext.Consumer>
);
}
}
Подробнее о новом API контекста можно узнать здесь .
createRef API
Ранее React предоставлял два способа управления ссылками ref
: устаревший
строковый ref
и обратный вызов. Хотя строковый ref
был более удобным из них, он имел
ряд недостатков, поэтому наша официальная рекомендация заключалась в том, чтобы
вместо него использовать обратный вызов.
Версия 16.3 добавляет новую опцию для управления ссылками ref
, которая предлагает
удобство строки ref
без каких-либо недостатков:
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.inputRef = React.createRef();
}
render() {
return <input type="text" ref={this.inputRef} />;
}
componentDidMount() {
this.inputRef.current.focus();
}
}
Внимание!
В дополнение к новомуcreateRef
API будет поддерживаться и обратный
вызов для ref
.
Вам не нужно заменять обратные вызовы для
ref
в ваших компонентах. Они немного более гибкие,
поэтому останутся в качестве продвинутой функции.
Подробнее о новом API createRef
читайте
здесь
.
forwardRef API
Компоненты более высокого порядка (или HOC) являются обычным способом повторного использования кода между компонентами. Основываясь на примере выше, мы могли бы создать HOC, который вводит текущую «тему» с помощью свойство:
function withTheme(Component) {
return function ThemedComponent(props) {
return (
<ThemeContext.Consumer>
{theme => <Component {...props} theme={theme} />}
</ThemeContext.Consumer>
);
};
}
Мы можем использовать вышеуказанный HOC для подключения компонентов к контексту темы,
без непосредственного использования ThemeContext
. Например:
class FancyButton extends React.Component {
buttonRef = React.createRef();
focus() {
this.buttonRef.current.focus();
}
render() {
const {label, theme, ...rest} = this.props;
return (
<button {...rest} className={`${theme}-button`} ref={this.buttonRef}>
{label}
</button>
);
}
}
const FancyThemedButton = withTheme(FancyButton);
// Мы можем отрисовать FancyThemedButton как если бы он был FancyButton
// Он будет автоматически получать текущую "theme",
// Также HOC будет передавать наши другие свойства.
<FancyThemedButton label="Click me!" onClick={handleClick} />;
HOC обычно передают props компонентам, которые они обертывают. К сожалению, ссылки не
передаются. Это означает, что мы не можем назначить ссылку на FancyButton
, если используем
FancyThemedButton
, поэтому нам не удастся вызвать focus()
.
Новый forwardRef
API решает эту проблему, предоставляя нам возможность
перехватить ссылку ref
и передать её как обычное свойство:
function withTheme(Component) {
function ThemedComponent({forwardedRef, ...rest}) {
return (
<ThemeContext.Consumer>
{theme => (
// Назначаем пользовательское свойство "forwardedRef" как ref
<Component {...rest} ref={forwardedRef} theme={theme} />
)}
</ThemeContext.Consumer>
);
}
// Обратите внимание на второй параметр "ref", предоставленный React.forwardRef.
// Мы можем передать его компоненту ThemedComponent как обычное свойство, например "forwardedRef".
// Затем он может быть назначен целевому компоненту.
return React.forwardRef((props, ref) => (
<ThemedComponent {...props} forwardedRef={ref} />
));
}
const fancyButtonRef = React.createRef();
// fancyButtonRef теперь будет указывать на FancyButton
<FancyThemedButton label="Click me!" onClick={handleClick} ref={fancyButtonRef} />;
Изменения методов жизненного цикла компонента
API React класса компонента в течение многих лет претерпевал небольшие изменения. Однако, поскольку мы добавляем поддержку более продвинутых функций (таких как границы ошибок и предстоящий асинхронный режим отрисовки), мы расширяем эту модель таким образом, что ничего подобного изначально это не предполагалось.
Например, с текущим API очень легко блокировать начальную отрисовку с несущественной логикой. Частично это связано с тем, что существует слишком много способов выполнить данную задачу, и может быть неясно, какой из них лучше. Мы заметили, что прерывание процесса обработки ошибок часто не учитывается и может привести к утечкам памяти (что также повлияет на предстоящий режим асинхронной отрисовки). Текущий API класса компонента также усложняет другие вещи, такую как наша работа по прототипированию компилятора React .
Многие из этих проблем усугубляются подмножеством следующих методов жизненного
цикла компонента: componentWillMount
, componentWillReceiveProps
и componentWillUpdate
.
Они вызывают наибольшую путаницу в сообществе React. По этим причинам мы хотим сделать
эти методы устаревшими в пользу лучших альтернатив.
Мы признаем, что это изменение повлияет на многие существующие компоненты. Из-за этого путь миграции будет как можно более постепенным и предоставит необходимые способы обхода проблем. (В Facebook мы поддерживаем более 50 000 компонентов React. Мы также зависим от постепенного цикла релиза!)
Внимание!
Предупреждения об устаревших компонентах будут доступны в будущих 16.x релизах, но устаревшие методы жизненного цикла будут продолжать работать до 17 версии.Даже в 17 версии их использование все равно будет возможно. Однако эти методы будут наделены префиксом «UNSAFE_» для указания, что они могут вызвать проблемы. Мы также подготовили , чтобы переименовать их в существующем коде.
Помимо устаревших небезопасных методов жизненного цикла, мы одновременно добавляем пару новых методов:
-
getDerivedStateFromProps
будет добавлен как более безопасная альтернатива устаревшемуcomponentWillReceiveProps
. -
getSnapshotBeforeUpdate
добавляется для обеспечения безопасного считывания свойств, например с DOM, перед выполнением обновлений.
Подробнее об этих изменениях читайте здесь.
Компонент StrictMode
StrictMode
- это инструмент для выделения потенциальных проблем в приложении.
Как и Fragment
, StrictMode
не отрисовывает видимый UI. Он активирует дополнительные
проверки и предупреждения для своих потомков.
Внимание!
ПроверкиStrictMode
выполняются только в режиме разработки; они не влияют на продакшен билд.
Хотя для strict mode
невозможно устранить все проблемы (например, определенные типы
мутаций), это может многим помочь. Если вы видите предупреждения в strict mode
, эти вещи,
скорее всего, приведут к багам при асинхронной отрисовке.
В версии 16.3, StrictMode
помогает с:
- Определением компонентов с небезопасными методами жизненного цикла.
- Предупреждения об использовании строкового
ref
API. - Обнаружение неожиданных сторонних эффектов.
Дополнительный функционал будет добавлен в будущих релизах React.
Подробнее о компоненте StrictMode
читайте здесь.