Главная » Хабрахабр » [Перевод] Вышел React v.16.3.0

[Перевод] Вышел 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 ( <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> ); }
}

Больше о 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 <input type="text" ref={this.inputRef} />; } 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 ( <ThemeContext.Consumer> {theme => <Component {...props} theme={theme} />} </ThemeContext.Consumer> ); };
}

Мы можем использовать этот 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 ( <button {...rest} className={`${theme}-button`} ref={this.buttonRef}> {label} </button> ); }
} const FancyThemedButton = withTheme(FancyButton); // Мы можем отрисовать FancyThemedButton, как будто это FancyButton
// Компонент автоматически получит текущую тему (*свойство theme*)
// И HOC прокинет его вниз через props.
<FancyThemedButton label="Click me!" onClick={handleClick}
/>;

Обычно HOC'и прокидывают свойства (props) в компонент, который они оборачивают. К сожалению, refs не прокидываются. Это значит, что мы не можем прикрепить ref к FancyButton когда используем FancyThemedButton. Выходит, вызвать focus() невозможно.

forwardRef API решает эту проблему, предлагая перехватить ref и послать его дальше как обычное свойство.

function withTheme(Component) { // обратите внимание, что "ref" предоставлен нам React.forwardRef. function ThemedComponent(props, ref) { return ( <ThemeContext.Consumer> {theme => ( <Component {...props} ref={ref} theme={theme} /> )} </ThemeContext.Consumer> ); } // Следующие несколько строк кода необязательны, // они нужны чтобы дать компоненту понятное имя в 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
<FancyThemedButton label="Click me!" onClick={handleClick} ref={fancyButtonRef}
/>;

Изменения в методах жизненного цикла (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 здесь.


x

Ещё Hi-Tech Интересное!

Google оштрафован на рекордные $5 млрд за нарушение антимонопольного законодательства в Европе

Это самый большой штраф в истории компании. Еврокомиссия закончила многолетнее расследование против Google и потребовала рекордный штраф в 5 миллиардов долларов (4,3 млрд евро). Товары из каталога Google Shop, согласно обвинению, намеренно ставились выше, чем остальные. Прошлый рекордный штраф, кстати, ...

«Яндекс» начал работу над созданием собственной системы «умный дом»

Сегодня стало известно о том, что компания «Яндекс» осенью может представить собственную систему «умный дом». Во всяком случае, она зарегистрировала в странах Евразийского экономического союза устройство «Яндекс.Модуль», о чем сообщает «Коммерсант». Этот девайс был создан американской компанией NotAnotherOne, у истоков ...