We have heard from many people that there is so much
work happening with React Native, it can be tough to
keep track of what's going on. To help communicate what
work is in progress, we are now publishing a
roadmap for React Native. At a high level, this work can be broken down into
three priorities:
Core Libraries. Adding more
functionality to the most useful components and APIs.
Stability. Improve the underlying
infrastructure to reduce bugs and improve code
quality.
Developer Experience. Help React
Native developers move faster
If you have suggestions for features that you think
would be valuable on the roadmap, check out
Canny, where you can suggest new features and discuss
existing proposals.
What's new in React Native
Version 0.37 of React Native, released today, introduces a new core component to
make it really easy to add a touchable Button to any
app. We're also introducing support for the new
Yarn package manager,
which should speed up the whole process of updating your
app's dependencies.
Introducing Button
Today we're introducing a basic
<Button /> component that looks great
on every platform. This addresses one of the most common
pieces of feedback we get: React Native is one of the
only mobile development toolkits without a button ready
to use out of the box.
<ButtononPress={onPressMe}title="Press Me"accessibilityLabel="Learn more about this Simple Button"
/>
Experienced React Native developers know how to make a
button: use TouchableOpacity for the default look on
iOS, TouchableNativeFeedback for the ripple effect on
Android, then apply a few styles. Custom buttons aren't
particularly hard to build or install, but we aim to
make React Native radically easy to learn. With the
addition of a basic button into core, newcomers will be
able to develop something awesome in their first day,
rather than spending that time formatting a Button and
learning about Touchable nuances.
Button is meant to work great and look native on every
platform, so it won't support all the bells and whistles
that custom buttons do. It is a great starting point,
but is not meant to replace all your existing buttons.
To learn more, check out the
new Button documentation, complete with a runnable example!
Speed up react-native init using Yarn
You can now use Yarn,
the new package manager for JavaScript, to speed up
react-native init significantly. To see the
speedup please
install yarn
and upgrade your react-native-cli to 1.2.0:
$ npm install -g react-native-cli
You should now see “Using yarn” when setting up new
apps:
In simple local testing
react-native init finished in
about 1 minute on a good network (vs
around 3 minutes when using npm 3.10.8). Installing yarn
is optional but highly recommended.
Thank you!
We'd like to thank everyone who contributed to this
release. The full
release notes
are now available on GitHub. With over two dozen bug
fixes and new features, React Native just keeps getting
better thanks to you.
Today we are releasing
React Native 0.36. Read on to learn more about what's new.
Headless JS
Headless JS is a way to run tasks in JavaScript while
your app is in the background. It can be used, for
example, to sync fresh data, handle push notifications,
or play music. It is only available on Android, for now.
To get started, define your async task in a dedicated
file (e.g. SomeTaskName.js):
module.exports=async(taskData)=>{// Perform your task here.};
Using Headless JS does require some native Java code to
be written in order to allow you to start up the service
when needed. Take a look at our new
Headless JS docs
to learn more!
The Keyboard API
Working with the on-screen keyboard is now easier with
Keyboard. You can now listen for native keyboard events and
react to them. For example, to dismiss the active
keyboard, simply call Keyboard.dismiss():
import{Keyboard}from'react-native';// Hide that keyboard!
Keyboard.dismiss();
Animated Division
Combining two animated values via addition,
multiplication, and modulo are already supported by
React Native. With version 0.36, combining two
animated values via division
is now possible. There are some cases where an animated
value needs to invert another animated value for
calculation. An example is inverting a scale (2x -->
0.5x):
const a = Animated.Value(1);
const b = Animated.divide(1, a);
Animated.spring(a, {
toValue:2,
}).start();
b will then follow a's spring
animation and produce the value of 1 / a.
In this example, the inner image won't get stretched at
all because the parent's scaling gets cancelled out. If
you'd like to learn more, check out the
Animations guide.
Dark Status Bars
A new barStyle value has been added to
StatusBar: dark-content. With
this addition, you can now use
barStyle
on both iOS and Android. The behavior will now be the
following:
default: Use the platform default (light
on iOS, dark on Android).
light-content: Use a light status bar
with black text and icons.
dark-content: Use a dark status bar with
white text and icons.
...and more
The above is just a sample of what has changed in 0.36.
Check out the
release notes on GitHub
to see the full list of new features, bug fixes, and
breaking changes.
You can upgrade to 0.36 by running the following
commands in a terminal:
After launching an app to the app stores,
internationalization is the next step to further your
audience reach. Over 20 countries and numerous people
around the world use Right-to-Left (RTL) languages.
Thus, making your app support RTL for them is necessary.
We're glad to announce that React Native has been
improved to support RTL layouts. This is now available
in the
react-native
master branch today, and will be available in the next
RC:
v0.33.0-rc.
This involved changing
css-layout, the core layout engine used by RN, and RN core
implementation, as well as specific OSS JS components to
support RTL.
To battle test the RTL support in production, the latest
version of the Facebook Ads Manager app
(the first cross-platform 100% RN app) is now available
in Arabic and Hebrew with RTL layouts for both
iOS
and
Android. Here is how it looks like in those RTL languages:
Overview Changes in RN for RTL support
css-layout
already has a concept of start and
end for the layout. In the Left-to-Right
(LTR) layout, start means
left, and end means
right. But in RTL, start means
right, and end means
left. This means we can make RN depend on
the start and end calculation
to compute the correct layout, which includes
position, padding, and
margin.
In addition,
css-layout
already makes each component's direction inherits from
its parent. This means, we simply need to set the
direction of the root component to RTL, and the entire
app will flip.
The diagram below describes the changes at high level:
Allow RTL layout for your app by calling the
allowRTL() function at the beginning of
native code. We provided this utility to only apply
to an RTL layout when your app is ready. Here is an
example:
iOS:
// in AppDelegate.m
[[RCTI18nUtil sharedInstance] allowRTL:YES];
Android:
// in MainActivity.javaI18nUtil sharedI18nUtilInstance =I18nUtil.getInstance();
sharedI18nUtilInstance.allowRTL(context,true);
For Android, you need add
android:supportsRtl="true" to
the
<application>
element in AndroidManifest.xml file.
Now, when you recompile your app and change the device
language to an RTL language (e.g. Arabic or Hebrew),
your app layout should change to RTL automatically.
Writing RTL-ready Components
In general, most components are already RTL-ready, for
example:
Left-to-Right Layout
Right-to-Left Layout
However, there are several cases to be aware of, for
which you will need the
I18nManager. In
I18nManager, there is a constant isRTL to tell if
layout of app is RTL or not, so that you can make the
necessary changes according to the layout.
Icons with Directional Meaning
If your component has icons or images, they will be
displayed the same way in LTR and RTL layout, because RN
will not flip your source image. Therefore, you should
flip them according to the layout style.
Left-to-Right Layout
Right-to-Left Layout
Here are two ways to flip the icon according to the
direction:
Or, changing the image source according to the
direction:
let imageSource =require('./back.png');if(I18nManager.isRTL){
imageSource =require('./forward.png');}return<Imagesource={imageSource}/>;
Gestures and Animations
In iOS and Android development, when you change to RTL
layout, the gestures and animations are the opposite of
LTR layout. Currently, in RN, gestures and animations
are not supported on RN core code level, but on
components level. The good news is, some of these
components already support RTL today, such as
SwipeableRow
and
NavigationExperimental. However, other components with gestures will need to
support RTL manually.
A good example to illustrate gesture RTL support is
SwipeableRow.
Even after the initial RTL-compatible app release, you
will likely need to iterate on new features. To improve
development efficiency,
I18nManager
provides the forceRTL() function for faster
RTL testing without changing the test device language.
You might want to provide a simple switch for this in
your app. Here's an example from the RTL example in the
RNTester:
<RNTesterBlocktitle={'Quickly Test RTL Layout'}><Viewstyle={styles.flexDirectionRow}><Textstyle={styles.switchRowTextView}>forceRTL</Text><Viewstyle={styles.switchRowSwitchView}><SwitchonValueChange={this._onDirectionChange}style={styles.rightAlignStyle}value={this.state.isRTL}/></View></View></RNTesterBlock>;_onDirectionChange=()=>{
I18nManager.forceRTL(!this.state.isRTL);this.setState({isRTL:!this.state.isRTL});
Alert.alert('Reload this page','Please reload this page to change the UI direction! '+'All examples in this app will be affected. '+'Check them out to see what they look like in RTL layout.',);};
When working on a new feature, you can easily toggle
this button and reload the app to see RTL layout. The
benefit is you won't need to change the language setting
to test, however some text alignment won't change, as
explained in the next section. Therefore, it's always a
good idea to test your app in the RTL language before
launching.
Limitations and Future Plan
The RTL support should cover most of the UX in your app;
however, there are some limitations for now:
Text alignment behaviors differ in iOS and Android
In iOS, the default text alignment depends on the
active language bundle, they are consistently on
one side. In Android, the default text alignment
depends on the language of the text content, i.e.
English will be left-aligned and Arabic will be
right-aligned.
In theory, this should be made consistent across
platform, but some people may prefer one behavior
to another when using an app. More user experience
research may be needed to find out the best
practice for text alignment.
There is no "true" left/right
As discussed before, we map the
left/right styles from the
JS side to start/end, all
left in code for RTL layout becomes
"right" on screen, and
right in code becomes "left"
on screen. This is convenient because you don't need
to change your product code too much, but it means
there is no way to specify "true left" or
"true right" in the code. In the future,
allowing a component to control its direction
regardless of the language may be necessary.
Make RTL support for gestures and animations more
developer friendly
Currently, there is still some programming effort
required to make gestures and animations RTL
compatible. In the future, it would be ideal to find
a way to make gestures and animations RTL support
more developer friendly.
Try it Out!
Check out the
RTLExample
in the RNTester to understand more about
RTL support, and let us know how it works for you!
Finally, thank you for reading! We hope that the RTL
support for React Native helps you grow your apps for
international audience!
Last week I had the opportunity to attend the
React Native Meetup
at Zynga’s San Francisco office. With around 200 people
in attendance, it served as a great place to meet other
developers near me that are also interested in React
Native.
I was particularly interested in learning more about how
React and React Native are used at companies like Zynga,
Netflix, and Airbnb. The agenda for the night would be
as follows:
Rapid Prototyping in React
Designing APIs for React Native
Bridging the Gap: Using React Native in Existing
Codebases
But first, the event started off with a quick
introduction and a brief recap of recent news:
The React Native Meetup community is growing fast!
There are now over 4,800 developers across a variety
of React Native meetup groups all over the globe.
The first round of news was followed by a quick
introduction by Zynga, our hosts for the evening.
Abhishek Chadha talked about how they use React to
quickly prototype new experiences on mobile, demoing a
quick prototype of a Draw Something-like app. They use a
similar approach as React Native, providing access to
native APIs via a bridge. This was demonstrated when
Abhishek used the device's camera to snap a photo of the
audience and then drew a hat on someone's head.
Designing APIs for React Native at Netflix
Up next, the first featured talk of the evening.
Clarence Leung, Senior Software Engineer at Netflix, presented his
talk on Designing APIs for React Native. First he noted
the two main types of libraries one may work on:
components such as tab bars and date pickers, and
libraries that provide access to native services such as
the camera roll or in-app payments. There are two ways
one may approach when building a library for use in
React Native:
Provide platform-specific components
A cross-platform library with a similar API for both
iOS and Android
Each approach has its own considerations, and it’s up to
you to determine what works best for your needs.
Approach #1
As an example of platform-specific components, Clarence
talked about the DatePickerIOS and DatePickerAndroid
from core React Native. On iOS, date pickers are
rendered as part of the UI and can be easily embedded in
an existing view, while date pickers on Android are
presented modally. It makes sense to provide separate
components in this case.
Approach #2
Photo pickers, on the other hand, are treated similarly
on iOS and Android. There are some slight differences —
Android does not group photos into folders like iOS does
with Selfies, for example — but those are easily handled
using if statements and the
Platform component.
Regardless of which approach you settle on, it’s a good
idea to minimize the API surface and build app-specific
libraries. For example, iOS’s In-App Purchase framework
supports one-time, consumable purchases, as well as
renewable subscriptions. If your app will only need to
support consumable purchases, you may get away with
dropping support for subscriptions in your
cross-platform library.
There was a brief Q&A session at the end of
Clarence’s talk. One of the interesting tid bits that
came out of it was that around 80% of the React Native
code written for these libraries at Netflix is shared
across both iOS and Android.
Bridging the Gap, Using React Native in Existing
Codebases
The final talk of the night was by
Leland Richardson
from Airbnb. The talk was focused on the use of React
Native in existing codebases. I already know how easy it
is to write a new app from scratch using React Native,
so I was very interested to hear about Airbnb’s
experience adopting React Native in their existing
native apps.
Leland started off by talking about greenfield apps
versus brownfield apps. Greenfield means to start a
project without the need to consider any prior work.
This is in contrast to brownfield projects where you
need to take into account the existing project’s
requirements, development processes, and all of the
teams various needs.
When you’re working on a greenfield app, the React
Native CLI sets up a single repository for both iOS and
Android and everything just works. The first challenge
against using React Native at Airbnb was the fact that
the iOS and Android app each had their own repository.
Multi-repo companies have some hurdles to get past
before they can adopt React Native.
To get around this, Airbnb first set up a new repo for
the React Native codebase. They used their continuous
integration servers to mirror the iOS and Android repos
into this new repo. After tests are run and the bundle
is built, the build artifacts are synced back to the iOS
and Android repos. This allows the mobile engineers to
work on native code without altering their development
enviroment. Mobile engineers don't need to install npm,
run the packager, or remember to build the JavaScript
bundle. The engineers writing actual React Native code
do not have to worry about syncing their code across iOS
and Android, as they work on the React Native repository
directly.
This does come with some drawbacks, mainly they could
not ship atomic updates. Changes that require a
combination of native and JavaScript code would require
three separate pull requests, all of which had to be
carefully landed. In order to avoid conflicts, CI will
fail to land changes back to the iOS and Android repos
if master has changed since the build started. This
would cause long delays during high commit frequency
days (such as when new releases are cut).
Airbnb has since moved to a mono repo approach.
Fortunately this was already under consideration, and
once the iOS and Android teams became comfortable with
using React Native they were happy to accelerate the
move towards the mono repo.
This has solved most of the issues they had with the
split repo approach. Leland did note that this does
cause a higher strain on the version control servers,
which may be an issue for smaller companies.
The Navigation Problem
The second half of Leland's talk focused on a topic that
is dear to me: the Navigation problem in React Native.
He talked about the abundance of navigation libraries in
React Native, both first party and third party.
NavigationExperimental was mentioned as something that
seemed promising, but ended up not being well suited for
their use case.
In fact, none of the existing navigation libraries seem
to work well for brownfield apps. A brownfield app
requires that the navigation state be fully owned by the
native app. For example, if a user’s session expires
while a React Native view is being presented, the native
app should be able to take over and present a login
screen as needed.
Airbnb also wanted to avoid replacing native navigation
bars with JavaScript versions as part of a transition,
as the effect could be jarring. Initially they limited
themselves to modally presented views, but this
obviously presented a problem when it came to adopting
React Native more widely within their apps.
They decided that they needed their own library. The
library is called airbnb-navigation. The
library has not yet being open sourced as it is strongly
tied to Airbnb’s codebase, but it is something they’d
like to release by the end of the year.
I won’t go into much detail into the library’s API, but
here are some of the key takeaways:
One must preregister scenes ahead of time
Each scene is displayed within its own
RCTRootView. They are presented natively
on each platform (e.g.
UINavigationControllers are used on iOS).
The main ScrollView in a scene should be
wrapped in a ScrollScene component. Doing
so allows you to take advantage of native behaviors
such as tapping on the status bar to scroll to the top
on iOS.
Transitions between scenes are handled natively, no
need to worry about performance.
The Android back button is automatically supported.
They can take advantage of View Controller based
navigation bar styling via a Navigator.Config UI-less
component.
There’s also some considerations to keep in mind:
The navigation bar is not easily customized in
JavaScript, as it is a native component. This is
intentional, as using native navigation bars is a hard
requirement for this type of library.
ScreenProps must be serialized/de-serialized whenever
they're sent through the bridge, so care must be taken
if sending too much data here.
Navigation state is owned by the native app (also a
hard requirement for the library), so things like
Redux cannot manipulate navigation state.
Leland's talk was also followed by a Q&A session.
Overall, Airbnb is satisfied with React Native. They’re
interested in using Code Push to fix any issues without
going through the App Store, and their engineers love
Live Reload, as they don't have to wait for the native
app to be rebuilt after every minor change.
Closing Remarks
The event ended with some additional React Native news:
Deco announced their
React Native Showcase, and invited everyone to add their app to the list.
Devin Abbott, one of the creators of Deco IDE, will be
teaching an introductory
React Native course.
Meetups provide a good opportunity to meet and learn
from other developers in the community. I'm looking
forward to attending more React Native meetups in the
future. If you make it up to one of these, please look
out for me and let me know how we can make React Native
work better for you!
Part of having a great developer experience is having
great documentation. A lot goes into creating good docs
- the ideal documentation is concise, helpful, accurate,
complete, and delightful. Recently we've been working
hard to make the docs better based on your feedback, and
we wanted to share some of the improvements we've made.
Inline Examples
When you learn a new library, a new programming
language, or a new framework, there's a beautiful moment
when you first write a bit of code, try it out, see if
it works... and it does work. You created
something real. We wanted to put that visceral
experience right into our docs. Like this:
We think these inline examples, using the
react-native-web-player
module with help from
Devin Abbott, are a great way to learn the basics of React Native,
and we have updated our
tutorial for new React Native developers
to use these wherever possible. Check it out - if you
have ever been curious to see what would happen if you
modified just one little bit of sample code, this is a
really nice way to poke around. Also, if you're building
developer tools and you want to show a live React Native
sample on your own site,
react-native-web-player
can make that straightforward.
The core simulation engine is provided by
Nicolas Gallagher's
react-native-web
project, which provides a way to display React Native
components like Text and
View on the web. Check out
react-native-web
if you're interested in building mobile and web
experiences that share a large chunk of the codebase.
Better Guides
In some parts of React Native, there are multiple ways
to do things, and we've heard feedback that we could
provide better guidance.
We have a new
guide to Navigation
that compares the different approaches and advises on
what you should use - Navigator,
NavigatorIOS,
NavigationExperimental. In the medium term,
we're working towards improving and consolidating those
interfaces. In the short term, we hope that a better
guide will make your life easier.
We also have a new
guide to handling touches
that explains some of the basics of making button-like
interfaces, and a brief summary of the different ways to
handle touch events.
When you start getting a React Native development
environment set up on your machine, you do have to do a
bunch of installing and configuring things. It's hard to
make installation a really fun and exciting experience,
but we can at least make it as quick and painless as
possible.
We built a
new Getting Started workflow
that lets you select your development operating system
and your mobile operating system up front, to provide
one concise place with all the setup instructions. We
also went through the installation process to make sure
everything worked and to make sure that every decision
point had a clear recommendation. After testing it out
on our innocent coworkers, we're pretty sure this is an
improvement.
We also worked on the
guide to integrating React Native into an existing
app. Many of the largest apps that use React Native, like
the Facebook app itself, actually build part of the app
in React Native, and part of it using regular
development tools. We hope this guide makes it easier
for more people to build apps this way.
We Need Your Help
Your feedback lets us know what we should prioritize. I
know some people will read this blog post and think
"Better docs? Pffft. The documentation for X is
still garbage!". That's great - we need that
energy. The best way to give us feedback depends on the
sort of feedback.
If you find a mistake in the documentation, like
inaccurate descriptions or code that doesn't actually
work,
file an issue. Tag it with "Documentation", so that it's
easier to route it to the right people.
If there isn't a specific mistake, but something in the
documentation is fundamentally confusing, it's not a
great fit for a GitHub issue. Instead, post on
Canny
about the area of the docs that could use help. This
helps us prioritize when we are doing more general work
like guide-writing.
Thanks for reading this far, and thanks for using React
Native!
It's been one year since we open-sourced React Native.
What started as an idea with a handful of engineers is
now a framework being used by product teams across
Facebook and beyond. Today at F8 we announced that
Microsoft is bringing
React Native to the Windows ecosystem, giving developers the potential to build React Native
on Windows PC, Phone, and Xbox. It will also provide
open source tools and services such as a React Native
extension for Visual Studio Code and CodePush to help
developers create React Native apps on the Windows
platform. In addition,
Samsung is
building React Native for its hybrid platform, which
will empower developers to build apps for millions of
SmartTVs and mobile and wearable devices. We also
released the
Facebook SDK for React Native, which makes it easier for developers to incorporate
Facebook social features like Login, Sharing, App
Analytics, and Graph APIs into their apps. In one year,
React Native has changed the way developers build on
every major platform.
It's been an epic ride — but we are only getting
started. Here is a look back at how React Native has
grown and evolved since we open-sourced it a year ago,
some challenges we faced along the way, and what we
expect as we look ahead to the future.
This is an excerpt. Read the rest of the post on
Facebook Code.
React Native allows you to build iOS and Android apps in
JavaScript using React and Relay's declarative
programming model. This leads to more concise,
easier-to-understand code; fast iteration without a
compile cycle; and easy sharing of code across multiple
platforms. You can ship faster and focus on details that
really matter, making your app look and feel fantastic.
Optimizing performance is a big part of this. Here is
the story of how we made React Native app startup twice
as fast.
Why the hurry?
With an app that runs faster, content loads quickly,
which means people get more time to interact with it,
and smooth animations make the app enjoyable to use. In
emerging markets, where
2011 class phones
on
2G networks
are the majority, a focus on performance can make the
difference between an app that is usable and one that
isn't.
Since releasing React Native on
iOS
and on
Android, we have been improving list view scrolling
performance, memory efficiency, UI responsiveness, and
app startup time. Startup sets the first impression of
an app and stresses all parts of the framework, so it is
the most rewarding and challenging problem to tackle.
This is an excerpt. Read the rest of the post on
Facebook Code.
React Native's goal is to give you the best possible
developer experience. A big part of it is the time it
takes between you save a file and be able to see the
changes. Our goal is to get this feedback loop to be
under 1 second, even as your app grows.
We got close to this ideal via three main features:
Use JavaScript as the language doesn't have a long
compilation cycle time.
Implement a tool called Packager that transforms
es6/flow/jsx files into normal JavaScript that the VM
can understand. It was designed as a server that keeps
intermediate state in memory to enable fast
incremental changes and uses multiple cores.
Build a feature called Live Reload that reloads the
app on save.
At this point, the bottleneck for developers is no
longer the time it takes to reload the app but losing
the state of your app. A common scenario is to work on a
feature that is multiple screens away from the launch
screen. Every time you reload, you've got to click on
the same path again and again to get back to your
feature, making the cycle multiple-seconds long.
Hot Reloading
The idea behind hot reloading is to keep the app running
and to inject new versions of the files that you edited
at runtime. This way, you don't lose any of your state
which is especially useful if you are tweaking the UI.
A video is worth a thousand words. Check out the
difference between Live Reload (current) and Hot Reload
(new).
If you look closely, you can notice that it is possible
to recover from a red box and you can also start
importing modules that were not previously there without
having to do a full reload.
Word of warning: because JavaScript is
a very stateful language, hot reloading cannot be
perfectly implemented. In practice, we found out that
the current setup is working well for a large amount of
usual use cases and a full reload is always available in
case something gets messed up.
Hot reloading is available as of 0.22, you can enable
it:
Open the developer menu
Tap on "Enable Hot Reloading"
Implementation in a nutshell
Now that we've seen why we want it and how to use it,
the fun part begins: how it actually works.
Hot Reloading is built on top of a feature
Hot Module Replacement, or HMR. It was first introduced by Webpack and we
implemented it inside of React Native Packager. HMR
makes the Packager watch for file changes and send HMR
updates to a thin HMR runtime included on the app.
In a nutshell, the HMR update contains the new code of
the JS modules that changed. When the runtime receives
them, it replaces the old modules' code with the new
one:
The HMR update contains a bit more than just the
module's code we want to change because replacing it,
it's not enough for the runtime to pick up the changes.
The problem is that the module system may have already
cached the exports of the module we want to
update. For instance, say you have an app composed of
these two modules:
The module log, prints out the provided
message including the current date provided by the
module time.
When the app is bundled, React Native registers each
module on the module system using the
__d function. For this app, among many
__d definitions, there will one for
log:
__d('log', function(){
... // module's code
});
This invocation wraps each module's code into an
anonymous function which we generally refer to as the
factory function. The module system runtime keeps track
of each module's factory function, whether it has
already been executed, and the result of such execution
(exports). When a module is required, the module system
either provides the already cached exports or executes
the module's factory function for the first time and
saves the result.
So say you start your app and require log.
At this point, neither log nor
time's factory functions have been executed
so no exports have been cached. Then, the user modifies
time to return the date in
MM/DD:
The Packager will send time's new code to the runtime
(step 1), and when log gets eventually
required the exported function gets executed it will do
so with time's changes (step 2):
Now say the code of log requires
time as a top level require:
const time = require('./time'); // top level require// log.jsfunctionlog(message) {
console.log(`[${time()}] ${message}`);
}
module.exports = log;
When log is required, the runtime will
cache its exports and time's one. (step 1).
Then, when time is modified, the HMR
process cannot simply finish after replacing
time's code. If it did, when
log gets executed, it would do so with a
cached copy of time (old code).
For log to pick up
time changes, we'll need to clear its
cached exports because one of the modules it depends on
was hot swapped (step 3). Finally, when
log gets required again, its factory
function will get executed requiring
time and getting its new code.
HMR API
HMR in React Native extends the module system by
introducing the hot object. This API is
based on
Webpack's one. The hot object exposes a function
called accept which allows you to define a
callback that will be executed when the module needs to
be hot swapped. For instance, if we would change
time's code as follows, every time we save
time, we'll see “time changed” in the console:
Note that only in rare cases you would need to use this
API manually. Hot Reloading should work out of the box
for the most common use cases.
HMR Runtime
As we've seen before, sometimes it's not enough only
accepting the HMR update because a module that uses the
one being hot swapped may have been already executed and
its imports cached. For instance, suppose the dependency
tree for the movies app example had a top-level
MovieRouter that depended on the
MovieSearch and
MovieScreen views, which depended on the
log and time modules from the
previous examples:
If the user accesses the movies' search view but not the
other one, all the modules except for
MovieScreen would have cached exports. If a
change is made to module time, the runtime
will have to clear the exports of log for
it to pick up time's changes. The process
wouldn't finish there: the runtime will repeat this
process recursively up until all the parents have been
accepted. So, it'll grab the modules that depend on
log and try to accept them. For
MovieScreen it can bail, as it hasn't been
required yet. For MovieSearch, it will have
to clear its exports and process its parents
recursively. Finally, it will do the same thing for
MovieRouter and finish there as no modules
depends on it.
In order to walk the dependency tree, the runtime
receives the inverse dependency tree from the Packager
on the HMR update. For this example the runtime will
receive a JSON object like this one:
React components are a bit harder to get to work with
Hot Reloading. The problem is that we can't simply
replace the old code with the new one as we'd loose the
component's state. For React web applications,
Dan Abramov
implemented a babel
transform
that uses Webpack's HMR API to solve this issue. In a
nutshell, his solution works by creating a proxy for
every single React component on transform time.
The proxies hold the component's state and delegate the
lifecycle methods to the actual components, which are
the ones we hot reload:
Besides creating the proxy component, the transform also
defines the accept function with a piece of
code to force React to re-render the component. This
way, we can hot reload rendering code without losing any
of the app's state.
The default
transformer
that comes with React Native uses the
babel-preset-react-native, which is
configured
to use react-transform the same way you'd
use it on a React web project that uses Webpack.
Redux Stores
To enable Hot Reloading on
Redux stores you will
just need to use the HMR API similarly to what you'd do
on a web project that uses Webpack:
When you change a reducer, the code to accept that
reducer will be sent to the client. Then the client will
realize that the reducer doesn't know how to accept
itself, so it will look for all the modules that refer
it and try to accept them. Eventually, the flow will get
to the single store, the
configureStore module, which will accept
the HMR update.
With React Native, we have the opportunity to rethink
the way we build apps in order to make it a great
developer experience. Hot reloading is only one piece of
the puzzle, what other crazy hacks can we do to make it
better?
With the recent launch of React on web and React Native
on mobile, we've provided a new front-end framework for
developers to build products. One key aspect of building
a robust product is ensuring that anyone can use it,
including people who have vision loss or other
disabilities. The Accessibility API for React and React
Native enables you to make any React-powered experience
usable by someone who may use assistive technology, like
a screen reader for the blind and visually impaired.
For this post, we're going to focus on React Native
apps. We've designed the React Accessibility API to look
and feel similar to the iOS and Android APIs. If you've
developed accessible applications for the web, iOS, or
Android before, you should feel comfortable with the
framework and nomenclature of the React AX API. For
instance, you can make a UI element
accessible (therefore exposed to assistive
technology) and use accessibilityLabel to
provide a string description for the element:
<View accessible={true} accessibilityLabel=”This is simple view”>
Let's walk through a slightly more involved application
of the React AX API by looking at one of Facebook's own
React-powered products: the
Ads Manager app.
This is an excerpt. Read the rest of the post on
Facebook Code.