React Native 0.71: TypeScript by Default, Flexbox Gap, and more...
Today we’re releasing React Native version 0.71! This is a feature-packed release including:
- TypeScript by default
- Simplifying layouts with Flexbox Gap
- Web-inspired props for accessibility, styles, and events
- Restoring PropTypes
- Developer Experience Improvements
- New Architecture Updates
In this post we’ll cover some of the highlights of 0.71.
For a full list of changes, check out CHANGELOG.md.
TypeScript by default
In this release, we’re investing in the TypeScript experience of React Native.
Starting with 0.71, when you create a new React Native app via the React Native CLI you'll get a TypeScript app by default. The new project is already set up with a tsconfig.json
so out of the box your IDE will help you write typed code right away.
We’re also offering built-in, more accurate TypeScript declarations directly from the react-native
package. This means you won’t need @types/react-native
any longer, and the types will be updated in lockstep with React Native releases.
Finally, our documentation has been updated to feature TypeScript for all examples.
After upgrading to React Native 0.71, we recommend removing @types/react-native
from your package.json devDependencies
.
For more details on this change, including migration steps and how this affects Flow users, check out our previous post First-class Support for TypeScript.
Simplifying layouts with Flexbox gap
With React Native you can flexibly layout components on different screen sizes using Flexbox. Browsers have supported the Flexbox properties gap, rowGap, and columnGap, which allow you to specify the amount of space between all items in a Flexbox.
These properties have been long requested in React Native, and 0.71 adds initial support for gaps defined using pixel values. In future versions, we will add support for more values, such as percentages.
To see why this is useful, imagine trying to build a responsive layout with variably sized cards, 10px apart from each other, hugging the edges of the parent container. Trying to accomplish this layout with child margins can be tricky.
The following shows a layout where we start by giving each child margin: 10
style:
Margins are applied uniformly to the edges of all children and don’t collapse under Flexbox, giving us spacing at the exterior of the cards, and double the space on the interior compared to what we wanted. We can get around this by applying non-uniform margins, using negative margins on the parent, halving our intended spacing, etc, but it can be made much easier.
With flex gap, this layout can be achieved by setting gap: 10
on the container for a 10 pixel gap between the interior of the cards:
For more information on Flexbox gaps, see this blogpost from CSS Tricks.
Web-inspired props for accessibility, styles, and events
This release includes a number of new props inspired by web standards to align React Native’s APIs across many platforms. These new props are purely additive so there are no expected migrations or change of behavior for equivalent accessibility, behavior, or style props.
For any new prop alias introduced, if there is an existing prop with a different name and both are specified, the new alias prop value will take precedence. For example, this release adds a src
prop alias for source
on the Image component to align with the src
prop on web. If both src
and source
are provided, the new src
prop will be used.
For more background on aligning React Native to web standards, check out this proposal and related discussion.
Accessibility
We introduced ARIA props as alias to existing React Native accessibility props.
These props now exist on all core components of React Native:aria-label
, aria-labelledby
,aria-modal
, id
, aria-busy
, aria-checked
, aria-disabled
, aria-expanded
, aria-selected
, aria-valuemax
, aria-valuemin
, aria-valuenow
, and aria-valuetext
.
We also introduced equivalent web behavior for: aria-hidden
, aria-live
, role
, and tabIndex
.
See this issue for more details.
Component-Specific Behavior
There were also props introduced to align prop names with equivalent DOM prop names for core components.
- Image:
alt
,tintColor
,crossOrigin
,height
,referrerPolicy
,src
,srcSet
, andwidth
. - TextInput:
autoComplete
,enterKeyHint
,inputMode
,readOnly
, androws
.
See this issue for more details.
Styles
To align with certain CSS styles, there have been feature extensions for the following styles:
aspectRatio
now supports string valuesfontVariant
now supports space-separated string valuesfontWeight
now supports number valuestransform
now supports string values
The following aliases have been added to shadow existing React Native styles:
See this issue for more details.
Events
Finally, we also added an opt-in implementation of PointerEvents
Once enabled, the following handlers on View
will support hover:
onPointerOver
,onPointerOut
onPointerEnter
,onPointerLeave
These events are also implemented in Pressability
for new opt-in support for hover.
To enable these features, set the following flags to true:
import ReactNativeFeatureFlags from 'react-native/Libraries/ReactNative/ReactNativeFeatureFlags';
// enable the JS-side of the w3c PointerEvent implementation
ReactNativeFeatureFlags.shouldEmitW3CPointerEvents = () => true;
// enable hover events in Pressibility to be backed by the PointerEvent implementation.
// shouldEmitW3CPointerEvents should also be true
ReactNativeFeatureFlags.shouldPressibilityUseW3CPointerEventsForHover = () =>
true;
Check out our dedicated PointerEvents post to learn more.
Restoring PropTypes
React Native’s prop types, such as ViewPropTypes
and Text.propTypes
, were deprecated in 0.66 and accessing them would output deprecation warnings. When they were removed in 0.68, many developers began experiencing errors when upgrading to the latest version of React Native.
After some investigation, we realized that a couple issues prevented the community from taking action on the deprecation warnings. First, the deprecation warning was not always actionable which caused people to ignore them (issue one, issue two). Second, the deprecation warnings were being incorrectly filtered by LogBox.ignoreLogs
. Both of these have now been fixed, but we want to give people more time to upgrade the deprecated call sites.
So in this release we are adding back React Native’s propTypes so that it is easier for people to upgrade and migrate their code to avoid using them. The deprecated-react-native-prop-types
package has also been updated for all of the props in 0.71. In the future, we plan to proceed with the deprecation and remove prop types once again. We expect that when we revisit the removal, the community will experience significantly fewer issues.
As part of this change, we are also removing the console filtering from LogBox.ignoreLog
. This means logs that you have previously filtered with Logbox.ignoreLog
will start appearing again in the console when you upgrade.
This is expected, because it allows logs such as deprecation warnings to be found and fixed.
Developer Experience Improvements
React DevTools
In this release, we've brought two popular React DevTools features on web to React Native.
"Click to inspect" is the option in the top left corner of React Dev Tools that allows you to click on an item in the app to inspect it in Dev Tools, similar to the Chrome element inspector.
Component highlighting will highlight the element you select in DevTools in the app so you can see which React components line up with which on-screen elements.
Here are both features in action:
Hermes
In React Native 0.70, we made Hermes the default engine for React Native.
In React Native 0.71, we’re upgrading Hermes with a few notable improvements:
- Improve source maps: By loading source maps over the network with Metro we’ve restored the ability to use source maps in recent versions of Chrome Dev Tools outside of Flipper.
- Improve
JSON.parse
performance: This version includes a performance optimization that improves the performance ofJSON.parse
up to 30%. - Add support for
.at()
: Hermes now supports.at()
forString
,TypedArray
, andArray
.
For a full list of changes see the Road to 71 issue.
New Architecture
This release brings many improvements to the experimental New Architecture experience based on user feedback and reports we collected so far.
- Reduced build times: The new distribution model uses Maven Central, which allows us to greatly reduce the build time on Android, resolves many build problems on Windows, and provides a more seamless experience with the New Architecture. Read more here.
- Write less C++ code: You can now enable the New Architecture without having to add any C++ code in your app and the CLI app template has been cleaned of all the C++ code and the CMake files. Read more here.
- Better encapsulation of iOS app setup: On iOS, we followed a similar approach to Android and encapsulated most of the logic to set up the New Architecture in the
RCTAppDelegate
class, which will simplify upgrades in the future with fewer manual breaking changes. - Better dependency management on iOS: For library maintainers, we've added a new
install_module_dependencies
function to call inside your packagepodspec
which will install all the required dependencies for the New Architecture. - Bug fixes and better IDE support: we fixed several bugs and issues (like better IDE support for Android) that were reported by our users in the New Architecture Working Group.
As a reminder, the New Architecture is still an experimental API experience as we iterate on changes to make adoption easier. Please try out the new simplified steps in the New Architecture documentation and post any feedback you have to the New Architecture Working Group.
Other Notable Fixes
- Better stack frame collapsing: We've updated the list of internal frames for React Native so LogBox will show your code more often rather than internal React Native frames, helping you to debug issues faster.
- Build time improvements: We migrated assets to Maven Central for prefabs to improve build times (both iOS and Android) for Hermes in both the current and new architectures.
- Android template improvements: The Android template was heavily cleaned and now fully relies on the React Native Gradle Plugin. You can find the configuration instructions directly inside the template or in the new dedicated page on the website.
Breaking changes
- Changes to Console Logging:
LogBox.ignoreLog
no longer filters console logs. This means you will start seeing logs in the console that you have silenced in LogBox. See this comment for more details. - Removed AsyncStorage and MaskedViewIOS: These components have been deprecated since version 0.59, so it’s time we remove them entirely. For alternatives, please check React Native Directory for community packages that cover those use cases.
- JSCRuntime moved to react-jsc: react-jsi is now split into react-jsc and react-jsi. If you use JSCRuntime, you will need to add react-jsc as a dependency (facebook/react-native@6b129d8).
Acknowledgements
This release is possible thanks to the work of 70+ contributors adding over 1000 commits.
We especially want to thank those who contributed to these major React Native projects:
- Flexbox Gap Support: @intergalacticspacehighway and @jacobp100.
- Web-inspired props: @gabrieldonadel @dakshbhardwaj @dhruvtailor7 @ankit-tailor @madhav23bansal.
- Codegen Improvements: @AntoineDoubovetzky, @MaeIg, @Marcoo09, @Naturalclar, @Pranav-yadav, @ZihanChen-MSFT, @dakshbhardwaj, @dhruvtailor7, @gabrieldonadel, @harshsiri110, @ken0nek, @kylemacabasco, @matiassalles99, @mdaj06, @mohitcharkha, @tarunrajput, @vinayharwani13, @youedd, @byCedric.
Finally, thanks to @cortinico, @kelset, @dmytrorykun, @cipolleschi, and @titozzz for cutting this release!
Try out 0.71.0 now!
For React Native CLI users, see the upgrade documentation for how to update your existing project, or create a new project with npx react-native init MyProject
.
React Native version 0.71 will be supported in Expo SDK version 48.
0.71 is now the latest stable version of React Native and 0.68.x versions are now unsupported. For more information see React Native’s support policy.