Developing react native application with umi

It seems that the front-end framework has entered the era of compile time since nextjs.

Since then, developers can quickly invest in the development of business code without building scaffolding, writing a pile of configuration and glue code to integrate various frameworks and so on.

After I got used to using umi on the Web side, I became more and more "lazy" and solved all problems with this hammer.

When the work involves the content of react native (hereinafter referred to as RN) application, it is found that umi has no intention to support RN for the time being.

After studying the code of umi from Github clone, the author found that the design of the whole umi engine is very scientific.

Based on the idea of umi plug-in, it is easy to extend some additional capabilities to support the development of RN.

This project came into being: umi-react-native.

umi is only used to generate intermediate code (temporary files) in RN, which is between coding and construction. It aims to introduce the development posture of umi to improve the RN programming experience.

Downstream can use:

  • React Native CLI : RN official development / packaging tool;
  • expo : there is no need to build iOS and Android development environment, the project directory is clean and refreshing, and adding RN dependency is convenient and fast;
  • haul : the third-party RN packer uses webpack. Disadvantages: Fast Refresh, Live Reloading and Hot Replacement are not supported.

The current version already supports:

  • Zero configuration, add dva@ant-design/react-native ... out of the box after dependence;
  • It only needs to focus on the implementation of page UI and business domain model, and all compilation configurations and HOC and context providers required for framework operation are completed by umi;
  • The routing scheme is used by default umi Built in react-router , optional react-navigation
  • Enable dynamicImport After configuration, unpacking is supported, and JS bundle files are loaded locally on demand at runtime.


This will be described in detail below umi-react-native How to use.

You can also skip this article and directly view the example project:

Unpacking will be carried out when the RN project meets the following conditions:


  • RN works;
  • umi 3.0 and above.


NPM package

brief introduction


Provide @ Ant Design / react native with on-demand loading, theme customization, preset, switching, internationalization support, and link font icons in expo.


The basic package enables umi to develop RN. React native version 0.44.0 and above (> = 0.44.0) is required


Use react navigation to replace react router to develop native applications. React native version 0.60.0 and above (> = 0.60.0) is required


It supports rendering the routing model defined by the react router in the way of react navigation. This dependency does not need to be installed separately


RN Bridge API provides JS layer with the ability to load Bundle files on demand. React native version 0.62.2 and above (> = 0.62.2) is required


If there is no RN project, use react native init to get the initial project:

npx react-native init UMIRNExample

Use yarn to add umi and umi preset react native dependencies in the RN project root directory:

yarn add umi umi-preset-react-native --dev

Integrated dva

Add @ umijs / plugin DVA dependency using yarn in RN project root directory:

yarn add @umijs/plugin-dva --dev

Integration @ Ant Design / react native

In RN project directory, use yarn to install @ Ant Design / react native:

yarn add @ant-design/react-native && yarn add umi-plugin-antd-react-native --dev

@Ant Design / react native current (2020 / 05 / 14) version: 3.x. To use 4.x, follow: Installation & use Operation.

Integrated react navigation (optional)

react-navigation Can be used as umi default react-router Alternatives.

need react-native 0.60.0 and above (> = 0.60. X)

Install all react-navigation Local dependence on RN project:

yarn add react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view

RN0.60.0 and above Auto Link Android will automatically handle these functions react-navigation However, for ios, after yarn installation is completed, you need to go to the ios directory and use pod to install:

cd ios && pod install


Finally, use yarn to install UMI preset react navigation:

yarn add umi-preset-react-navigation --dev

View Details: umi-preset-react-navigation.

to configure

All dependencies start with @umijs/preset-,@umijs/plugin-,umi-preset-,umi-plugin- will be registered as plugin/plugin-preset.

After umi 3.x, the plug-in will be automatically detected and assembled. So you don't need to configure it in. umirc.js plugins and presets.

Integrate other in RN umi The plug-in needs the discretion of the developer.

umi Plug ins include:

DOM independent umi All plug-ins can be used, or plug-ins supporting server-side rendering can basically be used in RN running environment.

UMI preset react native extension configuration

UMI preset react native will detect dependencies in the user project and automatically generate the required configuration files and entry files for the following tools.

It is recommended to add the following content at the end of the. gitignore file:

# umi-react-native

If your RN project uses only one development tool, no configuration is required.

If multiple development tools are installed in your RN project, you must specify which one is currently used through umi configuration:

use expo:

// .umirc.js
export default {
  expo: true,
  haul: false,

use haul:

// .umirc.js
export default {
  expo: false,
  haul: true,

use React Native CLI:

// .umirc.js
export default {
  expo: false,
  haul: false,

Babel configuration

use extraBabelPlugins and extraBabelPresets Add additional Babel configuration.

Metro configuration

Add additional Metro configuration Environment variables are required: UMI_ENV Specify the configuration file to load: metro.${UMI_ENV}.config.js.

For example, perform UMI_ When env = dev UMI g RN, the configuration in the file will be loaded. Use mergeConfig Merge with the configuration in metro.config.js.



Modify the package.json file:

  "scripts": {
    "android": "react-native run-android",
    "ios": "react-native run-ios",
    "start": "react-native start",
+   "watch": "umi g rn --dev",
    "test": "jest",
    "lint": "eslint ."

Start the watch process, listen for file changes, and regenerate the intermediate code:

yarn watch

Next, start another terminal, compile and start the Android Application:

yarn android

Compile and start iOS application:

yarn ios


First use umi to generate temporary code:

umi g rn

Reuse react-native bundle Build an offline bundle.


UMI preset react native provides two alternative routing schemes:

Use the react router built into umi

umi The built-in react router DOM is used by UMI preset react native alias Replace it with: react router native at compile time.

Both are based on react-router , but there are some differences.

The Link component is different in RN and DOM

The following are the properties of the react router native link component:

Link.propTypes= {
  onPress: PropTypes.func,
  component: PropTypes.elementType,
  replace: PropTypes.bool,
  to: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),

In RN, you can only use Link in this way:

import React from 'react';
import { Link } from 'umi';
import { List } from '@ant-design/react-native';

const Item = List.Item;

function Index() {
  return (
      <Link to="/home" component={Item} arrow="horizontal">
      <Link to="/login" component={Item} arrow="horizontal">
        Landing page

No NavLink components

React router native has no NavLink component. When you try to import it, you will get undefined:

import { NavLink } from 'umi';

typeof NavLink=== 'undefined'; // true;

New BackButton and AndroidBackButton components

For RN applications, you need to Global layout Use BackButton as the root container in:

// layouts/index.js
import React from 'react';
import { SafeAreaView, StatusBar } from 'react-native';
import { BackButton } from 'umi';
const Layout = ({ children }) => {
  return (

export default Layout;

In this way, when the user uses the Android system return key, he will return to the previous route of the application instead of exiting the application.

Using react navigation

Extended configuration

The following is the extended umi after installing umi preset react navigation to configure:


The theme field is optional. The default value is filled in the following example, which is equivalent to not filling in:

// .umirc.js
export default {
  reactNavigation: {
    // Use the ant design default color as the default theme for the navigation bar
    theme: {
      dark: false,
      colors: {
        primary: '#108ee9',
        background: '#ffffff',
        card: '#ffffff',
        text: '#000000',
        border: '#dddddd',

Extended runtime configuration

Check the umi documentation to see what: Runtime configuration.

The following are the extended after installing UMI preset react navigation Runtime configuration:


For async hronous functions, the returned promise resolve result will be passed to react navigation as the initial state.

Return type: promise < object | void | undefined >.


Customize the indicator / Loading during initialization of react navigation status. It usually takes effect after the above getReactNavigationInitialState is implemented.

By default:

  1. If not enabled dynamicImport Configuration, a built-in simple Loading will be used;
  2. If enabled dynamicImport If configured, dynamicImport.loading will be used;
    1. If the custom dynamicImport.loading is not implemented, dynamicImport The default Loading is also rudimentary.

The async function is used to subscribe to the react navigation status change notification and receive the latest status each time the route changes.

Case: persistent navigation state

app.js file in RN project root directory:

// app.js
import { Linking, Platform, Text } from 'react-native';
 * AsyncStorage It will be removed from the react native library in the future.
 * According to RN official documents:
import AsyncStorage from '@react-native-community/async-storage';


// Returns the status saved by local persistence, which is usually used in scenarios where application recovery and state recovery are required.
export async function getReactNavigationInitialState() {
  try {
    const initialUrl = await Linking.getInitialURL();
    if (Platform.OS !== 'web' && initialUrl == null) {
      const savedStateString = await AsyncStorage.getItem(PERSISTENCE_KEY);
      if (savedStateString) {
        return JSON.parse(savedStateString);
  } catch (ignored) {}

// Customizing the Loading displayed during returning to the initial state will take effect only if getReactNavigationInitialState is implemented.
export function getReactNavigationInitialIndicator() {
  // The following is the built-in simple Loading:
  return ({ error, isLoading }) => {
    if (__DEV__) {
      if (isLoading) {
        return React.createElement(Text, null, 'Loading...');
      if (error) {
        return React.createElement(
          React.createElement(Text, null, error.message),
          React.createElement(Text, null, error.stack),
    return React.createElement(Text, null, 'Loading...');

// Subscribe to the react navigation state change notification, and persist the navigation state to the local phone every time the route changes.
export async function onReactNavigationStateChange(state) {
  if (state) {
    await AsyncStorage.setItem(PERSISTENCE_KEY, JSON.stringify(state));
  • If you need @ react native community / async storage, please follow Installation;
  • After installation, remember to go to the ios directory and use pod to install native dependencies: CD ios & & pod install & & CD -, and then remember to recompile with yarn ios and yarn android to start the native App.

Extended Routing properties

Check the umi documentation to see what: Extended Routing properties.

Case: set navigation bar for a page separately

use Extended Routing properties Customize the top navigation bar:

import React from 'react';
import { Text } from 'react-native';
import { Button } from '@ant-design/react-native';

function HomePage({ navigation }) {
  // Handle button click events on the right side of the navigation bar
  function onHeaderRightPress() {
    // do something...

  // Set the buttons on the right side of the navigation bar
  useLayoutEffect(() => {
      headerRight: () => (
        <Button type="primary" size="small" onPress={onHeaderRightPress}>
  }, [navigation]);

  return <Text>Home Page</Text>;

// Extended Routing properties:
HomePage.title = 'Home Page';
HomePage.headerTintColor = '#000000';
HomePage.headerTitleStyle = {
  fontWeight: 'bold',
HomePage.headerStyle = {
  backgroundColor: '#ffffff',
// headerRight can also be written here:
// HomePage.headerRight = () => (
//  <Button type="primary" size="small">
//    Popup
//  </Button>
// );

export default HomePage;

If the title property of the page is not set, the global in. umirc.js is used title.

Jump between pages

To view umi documents: Jump between pages , the posture remains the same.

When using declarative Link components, it should be noted that RN is quite different from DOM:

import React from 'react';
import { Link } from 'umi';
import { List } from '@ant-design/react-native';

const Item = List.Item;

function Index() {
  return (
      <Link to="/home" component={Item} arrow="horizontal">
      <Link to="/login" component={Item} arrow="horizontal">
        Landing page

When you use the command jump page, you can only use the API of history. At present, UMI preset react navigation does not support it react-navigation You can only perform operations such as navigation bar settings.

Pass / receive parameters between pages

Click Link on the IndexPage and route to the HomePage with the query parameter:

import React from 'react';
import { Link } from 'umi';
import { List } from '@ant-design/react-native';

const Item = List.Item;

export default function IndexPage() {
  return (
      <Link to="/home?name=bar" component={Item} arrow="horizontal">
export default function HomePage({ route }) {
  console.log(route); // The route attribute field is shown below

  // ...

Example of route attribute:

{ "key": "/home-WnnfQomYXFls0kS0v0lxo", "name": "/home", "params": { "name": "bar" } }

Tags: ReactNative

Posted on Tue, 02 Nov 2021 05:55:20 -0400 by flash_78