Hire the top 3% of freelance React Native developers.

Toptal is a marketplace for top React Native developers, engineers, programmers, coders, architects, and consultants. Top companies and start-ups choose Toptal React Native freelancers for their mission critical software projects.
  • Trusted by:

Hire React Native developers and engineers

Matthew Keas, United States

Member since July 13, 2013
Matthew is an enthusiastic world traveler and follower of scientific computing, compilers, web development, and computer security. He has learned from universities and government organizations and worked for individual clients, startups, and more. He lives to solve p... Click to continue

Stanislav Krasnoyarov, Russia

Member since November 29, 2014
Stan is a CTO and a full-stack engineer with 15 years of experience. He has spent the past seven years doing web and mobile apps. He's good at designing architecture and implementing agile development process. The technologies he's worked with include: Node.js, Elixi... Click to continue

The Vital Guide to Interviewing React Native Developers

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 a React Native developer.

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 developer is proficient with JavaScript and especially with the ES6 syntax.

Many of the questions in our React hiring guide apply when hiring a React Native developer as well, so it is better to keep both guides in mind at the time of interview. Of course, the JavaScript hiring guide also applies: As the guide mentions, there’s a big difference between having some understanding of JavaScript 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 developer 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 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
    );
  }
}

What’s the best way to display items in a list, performance-wise?

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/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.

How does React Native behave across different platforms?

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, 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 Developer Candidate

The answers to these questions should give you an idea of how much a developer 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—there’s much more both to React Native development and to app development in general. For example, somebody 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 developer. Your mileage may vary, as with everything else in life. Good luck!

Hire React Native developers now