React Native is a library for rendering mobile applications on iOS, Android, and UWP. Using React Native, it’s possible (in most cases) to write code once and deploy to all available target platforms—which is probably why you’re looking to hire dedicated React Native experts.
React Native shares many concepts and libraries with React, so it’s important for any React Native job that the developer is at least familiar with React on the web and its common patterns. It’s also recommended that a React Native programmer is proficient with JavaScript and especially with the ES6 syntax.
Many of the questions in our React hiring guide apply when hiring app developers for React Native as well, so it is better to keep both guides in mind at the time of the interview. Of course, the JavaScript hiring guide also applies: As the guide mentions, there’s a big difference between having some understanding of the JavaScript framework and being an expert in it, and being a JavaScript expert is paramount when working on React and React Native jobs.
React Native Interview Questions
Let’s dive into some React Native interview questions to help you in the process of assessing your candidate.
What are React Native components?
Components are the building blocks of a React Native application. React Native provides a set of components that map to the corresponding native components on each platform which the React Native expert can use.
Some components can be used on all platforms (like View
, Button
, and FlatList
) while others are platform-specific, as they map to native components that exist only on iOS or Android: For example, iOS does not have a hardware back button, so a BackHandler
component for iOS apps would not make sense.
The developer can create their own component by extending the React.Component
class, and implementing the Render
method:
export default class App extends React.Component {
render() {
return (
// my component's visual tree
);
}
}
React Native offers a VirtualizedList
component that provides virtualization out of the box. While VirtualizedList
can be used directly, the more high-level FlatList
(display items in a scrollable list) and SectionList
(same as FlatList
but with grouping and custom sections) implementations are fit for most use cases.
Some things are important to keep in mind when working with a VirtualizedList
, however.
There’s no assurance that the internal state of the items in the list will be kept when scrolling the list: Based on the amount of elements and the level of scrolling, the list might dispose of some elements outside of the viewport. Those elements will be recreated from scratch based on props
when coming back into the viewport. So, the developer needs to make sure that the item can be recreated based on props
alone.
Items should specify a Key
property which identifies them uniquely. Alternatively, it’s possible to provide a custom KeyExtractor
in the list’s definition:
<FlatList KeyExtractor="{(item) => //function that uniquely identifies the item }" />
It’s a good practice to make sure list items do not re-render if passed in the same props they already have. This can be accomplished by implementing shouldComponentUpdate
in the item’s component, or alternatively inherit from the React.PureComponent
class, which provides an implementation of shouldComponentUpdate
that does shallow prop
and state
comparison.
How do you style components in React Native?
Styling is specified by plain JavaScript objects, and all React Native components accept a Style
prop that can be set with the object specifying the style.
Note that while the syntax resembles CSS, it’s not CSS, and styling a React Native application’s components does not follow the same conventions. Notably, all properties follow the camelCase convention instead of dash-case (background-color
becomes backgroundColor
) and layout can be specified only using the Flexbox algorithm.
Since style definitions are done in code, it is easy to parametrize styles and do things that usually CSS preprocessors/extensions (Less, Sass) are used for:
import { StyleSheet } from 'react-native';
import { primaryColor, secondaryColor } from './style/consts'; // values defined in another .js file
let width = 50;
///...
const style = StyleSheet.create({
'color': primaryColor,
'backgroundColor': secondaryColor,
'width': width
});
How would you debug a React Native application?
While running a React Native application in the emulator, it’s possible to access the developer menu by either “shaking” the device (by selecting the “shake” gesture in the emulator) or by pressing Command-D (iOS) or Control/Command-M (Android). The developer menu will display a “enable JS debugging” menu entry, among other things. After clicking it, it will be possible to browse to http://localhost:8081/debugger-ui with Chrome/Chromium, which displays the debugger.
Log traces are visible by running react-native log-android
for Android, and react-native log-ios
for iOS, while the emulator is up.
If using Redux, Reactotron is especially useful to see all API calls and actions dispatched.
Our existing codebase is in Xamarin, and you would be helping to port it to React Native. What would be the issues to watch for?
Unlike our other React Native interview questions, this may not apply to every project. But if it does, it’s certainly an important line of questioning to consider.
React Native and Xamarin.Forms adopt the same approach towards making cross-platform applications: Both take a UI definition (virtual DOM or XAML) and transform it to native code.
There are two main differences between the two:
- The language of choice: It’s almost always C# for Xamarin—though potentially any other language available for the .NET framework—and JavaScript for React Native.
- The development platforms they’re available on: React Native is available for Linux, MacOS, and Windows, while Xamarin is officially available only on Windows and MacOS.
While React Native and Xamarin.Forms do conceptually the same thing, the abstractions they use are not directly compatible. For example, a component available on React Native might not necessarily be available on Xamarin, and vice versa. Also, the same abstraction is often implemented in different ways across the two frameworks: Take FlatList
and SectionList
on React Native, which map to their corresponding concept on both iOS and Android, and ListView
on Xamarin.Forms, which conflates the two into one single UI component.
If a React Native developer were to tackle a port from Xamarin.Forms, it would be greatly beneficial for them to have at least some experience with C#, and ideally some experience with Xamarin.
What’s the relationship between React and React Native?
React is a JavaScript library that allows the developer to define a user interface in a declarative way. If offers some infrastructure when it comes to state handling (props
for one-way data flow, injected from the outside; state
for two-way data flow, internally managed state) and general component lifecycle method hooks.
React keeps in memory an internal representation of the UI (virtual DOM). It uses this representation to compute deltas in the visual appearance of the components on props/state changes, in order to make it possible to partially update the UI on data changes—thus avoiding the need for complete redraws.
React Native sits on top of React and, where React would render the virtual DOM as an HTML document, React Native maps the virtual DOM to native iOS/native Android components. So, while React is often used together with JSX in order to generate HTML output, React Native has its own set of tags that represent abstractions of native components. Those native components are what get displayed on the device in the end.
So, if a React component would look like the following:
class ReactJSComponent extends React.Component {
render() {
return(
<div>
<p>Hello world!</p>
</div>
);
}
}
…then an equivalent React Native component could be something like:
class ReactNativeComponent extends React.Component { //note that's the same class we're extending
render() {
return(
<View>
<Text>Hello world!</Text>
</View>
);
}
}
Libraries that are often use to handle state (Redux, MobX) and most plugins that are not dependent on UI are used the exact same way in React and React Native, and most patterns/best practices that apply to React apply to React Native too.
Highlight the major differences and tradeoffs between native development and mobile development using React Native.
React Native has clear benefits when it comes to mobile application development:
- React Native allows for cross-platform development: The application logic is written once, using the same language (JavaScript) and can be deployed to the available target platforms (iOS, Android, and UWP). Writing an application natively for a specific platform requires instead an almost complete rewrite when porting said application to a different platform.
- A React Native app, with some limitations (see below), is written in JavaScript. That can be a plus or a minus depending on the situation, but generally, finding developers that are experienced with JavaScript is not as hard as for other languages.
- Hot reloading is a great React Native feature, allowing the developer to change the application code and see those changes directly in the emulator, with no need for recompiling/redeploying.
React Native is a strong choice, especially considering the ever-increasing user base and continuous improvements made to it. But there are some drawbacks to be considered:
- While performance has been improving steadily over the last two years, React Native is still significantly slower than a visually equivalent native application, especially when the application makes heavy use of animations or has a complex UI.
- Some native functionality is not available for use directly from React Native, and it might be necessary to write modules for each target platform, in the target platform’s language.
- JavaScript is a mainstream language and thus widely known and used, but it has some serious drawbacks. It might be challenging to write and maintain a JavaScript application that scales up to a certain size.
React Native takes the virtual DOM, generated by React based on the interface definition—i.e. the result gotten from calling the render
method on the application’s components. It then uses this to generate native code for each of the target platforms.
That means that, for the most part, the developer doesn’t have to worry about platform-specific details and can rely on React Native outputting the right native code based on the situation. For example, if the developer adds a Text
component, it will be transformed into a UITextField
on iOS, and into a TextView
on Android. The same goes for layout definitions: React Native uses flexbox, and that is translated as proper layout definitions specific to the target platform when the application is deployed.
Sometimes the abstraction provided by React Native is available only on some of the target platforms (an example would be the already-mentioned BackHandler
). When that’s the case, it is up to the developer to properly make use of the abstraction. A check for the current platform might be necessary:
import {Platform} from 'react-native';
if (Platform.OS == 'ios') {
// iOS-specific code
}
There are some cases where React Native does not provide an abstraction layer over native components or functionalities. In those cases, the developer will have to write a native module, in the target platform’s language. That is done by extending the ReactContextBaseJavaModule
for Android apps, and by implementing the RCTBridgeModule
in iOS.
With those modules in place, it’s possible to interact with them from React Native using the endpoints explicitly provided by the modules themselves. We simply annotate methods with @ReactMethod
on Android and by exporting classes and methods with RCT_EXPORT_MODULE
and RCT_EXPORT_METHOD
on iOS:
public class MyModule extends ReactContextBaseJavaModule {
@ReactMethod
public void myMethod() {
// implementation
}
}
@implementation MyModule
RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(myMethod)
{
// implementation
}
import {NativeModules} from 'react-native';
// call it like this:
NativeModules.MyModule.myMethod();
What are the different options available when it comes to handling state in React Native?
As it is, React (and thus React Native) does not enforce any kind of global state management. The only patterns available to use for the developer are injecting state into components using props
, which are meant to be immutable, and internal component state managed privately through the state
property.
There are several options available when it comes to global state management, the more widely used being Redux. If the developer is familiar with Redux on React, there are no changes for when it comes to using it on React Native. The behavior is exactly the same, as are the common patterns of use.
Another available option to manage global state is MobX, which handles state using observables and bindings, the way Knockout.js and WPF do. While Redux follows functional programming paradigms—and is suited to that kind of programming style, for that reason—MobX can be easier to pick up for those coming from an object-oriented background.
Both options are valid, and it’s important to consider the team’s composition before picking one or the other. Redux is often the choice preferred by those with a functional programming background, but it can be challenging to get up to speed with. MobX offers a flatter learning curve, but it might show problems when the application grows up to a certain size.
What is a Thunk?
Generally speaking, a Thunk is a function returned by another function. It is used to defer computing a result to when the result is actually needed:
function doMyThing() {
return function() {
return "my result";
}
}
The concept is important for the React (and React Native) developer because they’re used in one of the most popular pieces of middleware for Redux: redux-thunk. That allows React actions, which are normally just plain JavaScript objects, like this:
{
type: "MY_ACTION_TYPE",
value: "myvalue"
}
…to actually dispatch other actions directly, like so:
function myActionCreator() {
return function(dispatch, state) {
dispatch(anotherActionCreator());
}
}
There are other pieces of middleware for Redux that do not expose the concept directly—the most famous being React Saga—but it’s very important that your React Native developer candidate is comfortable with functional programming concepts like the above.
What is middleware? How is it used in Redux?
Redux middleware is a function provided to Redux by the developer (either imported from an external module, or developed directly) that intercepts all actions dispatched before they reach the reducers, potentially does some operations on those actions, and forwards them to the reducers afterwards.
Middleware thus provides a hook that can be used to run custom operations on actions before they reach the reducers. This is important, as many libraries and extensions (e.g., the aforementioned redux-thunk) register themselves as middleware. A piece of middleware returns a Thunk, as it is a function that returns a function.
A sample middleware implementation looks like this:
// middleware that does nothing
const myMiddleware = store => next => action => {
return next(action);
}
Here, store
is the application’s store, available from inside the middleware function. That means that store.dispatch
is available from inside the middleware, thus making it possible to dispatch more than one action per action received—beware of infinite loops! Then next
is a function that returns a function (which will dispatch the action) and expects an action as the parameter.
The above middleware can be registered using the following:
const store = createStore(
myCombinedReducers,
applyMiddleware(myMiddleware, otherMiddleware)
)
Gauging Your React Native App Development Candidate
The answers to these questions should give you an idea of how much a mobile app development candidate is comfortable working with React Native.
This hiring guide, of course, was not meant to cover an exhaustive interview, but to act as a guideline for hiring full-time or part-time experts—–there’s much more both to React Native development and to app development in general. For example, a dedicated developer who is very experienced with both JavaScript and React should be able to pick up React Native and its concepts in no time.
At the same time, someone who has been working a bit with React Native development but does not have extensive experience with JavaScript or with native development might know the answers to the questions above, but not be very effective as a React Native app developer. Your mileage may vary, as with everything else in life. Good luck!