# MRZ Scanner User Guide (React Native Edition)

The Dynamsoft MRZ Scanner (React Native Edition) provides a ready-to-use scanning component that lets you add MRZ reading to your app with minimal setup. This guide walks through building a complete MRZ scanning app from scratch using `MRZScanner` — the built-in component that handles the camera UI, scanning logic, and result delivery.

> [!IMPORTANT]
> For the full sample code, visit the [ScanMRZ sample on GitHub](https://github.com/Dynamsoft/mrz-scanner-mobile-react-native).

## Supported Document Types

The SDK supports three ICAO Machine Readable Travel Document (MRTD) formats: **TD1** (ID cards, 3-line MRZ), **TD2** (ID cards, 2-line MRZ), and **TD3** (passports, 2-line MRZ). For a visual reference of each format, see [Supported Document Types](https://www.dynamsoft.com/mrz-scanner/docs/mobile/programming/shared/supported-document-types.md).

> [!NOTE]
> For support for other MRTD types, contact the [Dynamsoft Support Team](https://www.dynamsoft.com/contact).

## System Requirements

The SDK supports React Native **0.71.0** or higher. The toolchain versions below correspond to the React Native version this guide's sample is pinned to (**0.85.3**). If you target a different React Native version, your Node, JDK, Gradle, Xcode, and iOS deployment-target requirements are dictated by *that* version — check its release requirements rather than the values here.

- React Native **0.71.0** or higher (this guide is pinned to **0.85.3**).
- Node **20.19.4** or higher.
- Android
  - Supported OS: **Android 5.0** (API Level 21) or higher.
  - Supported ABI: **armeabi-v7a**, **arm64-v8a**, **x86** and **x86_64**.
  - Development Environment: **Android Studio 2022.2.1+** (2025.2.1 recommended), **Java 17–20**, **Gradle 9.x**.
- iOS
  - Supported OS: **iOS 15.1** or higher.
  - Supported ABI: **arm64** and **x86_64**.
  - Development Environment: **Xcode 16.1** or higher.

## Licensing

A valid license key is required to use the SDK. If you are just getting started, request a free 30-day trial license below:

<link href="/webres/wwwroot/css/intlTelInput.min.css" rel="stylesheet" />
<script src="/webres/wwwroot/js/intlTelInput.min.js"></script>
<script src="/webres/wwwroot/js/docs/dayjs.min.js"></script>
<link rel="stylesheet" href="/webres/wwwroot/fontawesome-free-5.13.0-web/css/all.min.css" />
<link rel="stylesheet" href="/webres/wwwroot/css/docs/trialLicense.css" />

<div class="trial-license-wrap" style="display: none;">
  <div class="not-logged-in hide">
    <p class="title">Request a Trial License</p>
    <div class="result">
      <div class="key">Demo: DLS2eyJvcmdhbml6YXeyJo34567AwMDAxLTEwM34XphdGlvbk812345AxIn0= </div>
      <div type="button" class="d-btn orange-btn reveal-btn">Reveal</div>
    </div>
  </div>
  <div class="had-license hide">
    <p class="title">Your Trial License <span class="expiredTime"></span></p>
    <div class="result">
      <div class="key">
        DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9DLS2eyJoYW5kc2hha2VDb2RlIjoiMjAwMDAxLTEwMTIwMDkzNiIsIm9yZ2FuaXphdGlvbklEIjoiMjAwMDAxIn0=
      </div>
      <i class="fa fa-copy"></i>
      <div type="button" class="d-btn orange-btn copy-btn">Copy</div>
      <div type="button" class="d-btn orange-btn extend-btn" style="display: none;">Extend</div>
    </div>
    <p class="note" style="display: none;color: #ec403d;">You've reached the limit for trial requests. Please <a href="/contact/">contact our support team</a>, and we will be happy to extend additional time for you.​</p>
    <span class="copyied">Copied!</span>
  </div>
  <div class="request-success hide">
    <p class="title">Request a Trial License - Successful</p>
    <div class="desc">
      <i class="icon-send"></i>
      <p>The license will be sent to your email immediately. If you don't see it in your inbox, please check your
        junk/spam folder as well.</p>
    </div>
  </div>
</div>

<div class="modal trial-license-request-modal" tabindex="-1">
  <div class="modal-dialog modal-dialog-centered">
    <div class="modal-content">
      <i class="icon-close"></i>
      <div class="modal-body">
        <div class="loading" id="loadingLogin" style="display: none;">
          <div class="lds-ring">
            <div></div>
            <div></div>
            <div></div>
            <div></div>
          </div>
        </div>
        <div class="emailErrorAlert off">
          <div class="ds-alert error">
            <p>We are unable to deliver to the email address provided. Please try a different one.</p>
            <div class="ds-alert-close-btn"></div>
          </div>
        </div>
        <div class="third-party-request">
          <p>One Click to Request a 30-Day Trial License</p>
          <div class="login-btns">
            <div type="button" class="third-party-btn github-btn"><i class="fab fa-github"></i>Github</div>
            <div type="button" class="third-party-btn microsoft-btn"><i class="fab fa-microsoft"></i>Microsoft</div>
            <div type="button" class="third-party-btn google-btn">
              <div class="gsi-material-button-icon">
                  <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" xmlns:xlink="http://www.w3.org/1999/xlink" style="display: block;">
                      <path fill="#EA4335" d="M24 9.5c3.54 0 6.71 1.22 9.21 3.6l6.85-6.85C35.9 2.38 30.47 0 24 0 14.62 0 6.51 5.38 2.56 13.22l7.98 6.19C12.43 13.72 17.74 9.5 24 9.5z"></path>
                      <path fill="#4285F4" d="M46.98 24.55c0-1.57-.15-3.09-.38-4.55H24v9.02h12.94c-.58 2.96-2.26 5.48-4.78 7.18l7.73 6c4.51-4.18 7.09-10.36 7.09-17.65z"></path>
                      <path fill="#FBBC05" d="M10.53 28.59c-.48-1.45-.76-2.99-.76-4.59s.27-3.14.76-4.59l-7.98-6.19C.92 16.46 0 20.12 0 24c0 3.88.92 7.54 2.56 10.78l7.97-6.19z"></path>
                      <path fill="#34A853" d="M24 48c6.48 0 11.93-2.13 15.89-5.81l-7.73-6c-2.15 1.45-4.92 2.3-8.16 2.3-6.26 0-11.57-4.22-13.47-9.91l-7.98 6.19C6.51 42.62 14.62 48 24 48z"></path>
                      <path fill="none" d="M0 0h48v48H0z"></path>
                  </svg>
              </div>
              Google
            </div>
          </div>
        </div>
        <p class="devide">or continue with a work email</p>
        <div class="dynamsoft-request">
          <div class="basicForm">
            <div class="basicFormGroup" style="grid-area: a">
              <input type="email" id="Email" name="email" class="basicFormInput" autofocus placeholder=" " />
              <div class="placeholder"><span>*</span> Business Email Address</div>
            </div>
            <div class="clearfix" style="grid-area: b">
              <div class="basicFormGroup fl" style="width: 49.5%">
                <input type="text" id="FirstName" class="basicFormInput" placeholder=" ">
                <div class="placeholder"><span>*</span> First Name</div>
              </div>
              <div class="basicFormGroup fr" style="width: 49.5%">
                <input type="text" id="LastName" class="basicFormInput" placeholder=" ">
                <div class="placeholder"><span>*</span> Last Name</div>
              </div>
            </div>
            <div class="basicFormGroup companyField" style="grid-area: c">
              <input type="text" id="CompanyName" class="basicFormInput" placeholder=" ">
              <div class="placeholder"><span>*</span> Company Name</div>
            </div>
            <div class="basicFormGroup phoneNumberField" style="grid-area: d">
              <input type="tel" id="PhoneNumber" class="basicFormInput" autocomplete="new-password" placeholder=" ">
              <div class="placeholder"><span>*</span> Phone Number</div>
            </div>
          </div>
          <div class="generateLine">
            <div type="button" class="generateLicense" value="Generate a License">Generate a License</div>
            <p>The license will be sent to your email immediately.</p>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

<div class="modal trial-license-extend-modal" tabindex="-1">
  <div class="modal-dialog modal-dialog-centered">
    <div class="modal-content">
      <i class="icon-close"></i>
      <div class="modal-body">
        <div class="businessEmailFormGroup">
          <div class="basicForm tc businessEmailForm" style="position: relative;">
            <div class="businessEmailErrorAlert off">
              <div class="ds-alert error">
                <p>We are unable to deliver to the email address provided. Please try a different one.</p>
                <div class="ds-alert-close-btn"></div>
              </div>
            </div>
            <div class="businessEmailStep">
              <h3 class="title mb20 tl">Link your business email</h3>
              <p class="mb20 tl desc">To extend your trial, please link your business email. We use it to keep your license and account records together.</p>
              <div class="collectUserInfo">
                <div class="basicFormGroup">
                  <input name="businessEmail" id="businessEmail" type="email" class="basicFormInput" placeholder=" " required>
                  <div class="placeholder"><span>*</span> Business Email</div>
                </div>
              </div>
              <p class="businessEmailLockedNote tl" style="display: none;">This business email cannot be changed. If you need to update it, please contact our sales team.</p>
              <button class="d-btn border-btn verifyBusinessEmailBtn fontOswald">Verify &amp; extend my trial</button>
            </div>
            <div class="businessEmailCodeStep" style="display: none;">
              <h3 class="title mb20 tl">Enter verification code</h3>
              <p class="mb20 tl desc">We've sent a 6-digit verification code to <span class="businessEmailCodeTarget"></span>. Enter it below to link your business email and extend your trial.</p>
              <div class="collectUserInfo">
                <div class="basicFormGroup">
                  <input type="text" id="businessEmailVerifyCode" class="basicFormInput" placeholder=" " maxlength="6" inputmode="numeric" autocomplete="one-time-code" required>
                  <div class="placeholder"><span>*</span> Verification Code</div>
                </div>
              </div>
              <button class="d-btn border-btn confirmBusinessEmailCodeBtn fontOswald">Confirm &amp; extend my trial</button>
              <div class="resendBusinessEmailCodeLine">
                <a href="javascript:;" class="orangeLink resendBusinessEmailCode">Resend verification code</a>
              </div>
            </div>
            <div class="businessEmailPasswordStep" style="display: none;">
              <h3 class="title mb20 tl">Verify ownership</h3>
              <p class="mb20 tl desc">This business email is associated with an existing account. Enter the password of <span class="businessEmailPasswordTarget"></span> to verify ownership and extend your trial.</p>
              <div class="collectUserInfo">
                <div class="basicFormGroup">
                  <input type="password" id="businessEmailPassword" class="basicFormInput" placeholder=" " autocomplete="current-password" required>
                  <div class="placeholder"><span>*</span> Password</div>
                </div>
              </div>
              <button class="d-btn border-btn confirmBusinessEmailPasswordBtn fontOswald">Verify &amp; extend my trial</button>
              <div class="resetBusinessEmailPasswordLine">
                <a href="javascript:;" class="orangeLink resetBusinessEmailPassword">Forgot password?</a>
              </div>
            </div>
          </div>
        </div>
        <div class="extensionSurvey">
          <div class="survey survey1">
            <div class="form-group">
              <label class="control-label">Are you building an app for your own company or for a client? <span
                  class="fontOrange">*</span></label>
              <div class="radio-group">
                <div class="radio">
                  <label class="radio">
                    <input name="BuildingAppUser" id="BuildingAppUser1" type="radio" value="Own Company" required>
                    <label for="BuildingAppUser1"><span>Own Company</span></label>
                  </label>
                </div>
                <div class="radio">
                  <label class="radio">
                    <input name="BuildingAppUser" id="BuildingAppUser2" type="radio" value="A Client">
                    <label for="BuildingAppUser2"><span>A Client</span></label>
                  </label>
                </div>
              </div>
            </div>
            <div class="form-group">
              <label class="control-label">Which one of the following deployment types best describes your <span
                  class="showQ1A2" style="display: none;">client's</span> usage scenario? <span
                  class="fontOrange">*</span></label>
              <div class="radio-group">
                <div class="radio">
                  <label class="radio">
                    <input name="UsageScenario" data-businessType="100000000" id="UsageScenario1" type="radio"
                      value="Internal use by employees and contractors of my company only" required>
                    <label for="UsageScenario1"><span>Internal use by employees and contractors of my <span
                          class="showQ1A2" style="display: none;">client's</span> company only</span></label>
                  </label>
                </div>
                <div class="radio">
                  <label class="radio">
                    <input name="UsageScenario" data-businessType="100000002" id="UsageScenario2" type="radio"
                      value="Hosted software/service for consumption by customers (e.g., SaaS)">
                    <label for="UsageScenario2"><span>Hosted software/service for consumption by customers (e.g.,
                        SaaS)</span></label>
                  </label>
                </div>
                <div class="radio">
                  <label class="radio">
                    <input name="UsageScenario" data-businessType="100000001" id="UsageScenario3" type="radio"
                      value="Product for sale to customers for on-premises use">
                    <label for="UsageScenario3"><span>Product for sale to customers for on-premises use</span></label>
                  </label>
                </div>
              </div>
            </div>
            <div class="form-group">
              <label class="control-label">When do you need to release your application with the SDK feature integrated?
                <span class="fontOrange">*</span></label>
              <div class="radio-group">
                <div class="radio">
                  <label class="radio">
                    <input name="ReleaseTime" id="ReleaseTime1" type="radio" value="Less than a week" required>
                    <label for="ReleaseTime1"><span>Less than a week</span></label>
                  </label>
                </div>
                <div class="radio">
                  <label class="radio">
                    <input name="ReleaseTime" id="ReleaseTime2" type="radio" value="Less than a month">
                    <label for="ReleaseTime2"><span>Less than a month</span></label>
                  </label>
                </div>
                <div class="radio">
                  <label class="radio">
                    <input name="ReleaseTime" id="ReleaseTime3" type="radio" value="1 to 3 months">
                    <label for="ReleaseTime3"><span>1 to 3 months</span></label>
                  </label>
                </div>
                <div class="radio">
                  <label class="radio">
                    <input name="ReleaseTime" id="ReleaseTime4" type="radio" value="3 to 6 months">
                    <label for="ReleaseTime4"><span>3 to 6 months</span></label>
                  </label>
                </div>
                <div class="radio">
                  <label class="radio">
                    <input name="ReleaseTime" id="ReleaseTime5" type="radio" value="More than 6 months">
                    <label for="ReleaseTime5"><span>More than 6 months</span></label>
                  </label>
                </div>
              </div>
            </div>
            <div class="form-group">
              <label class="control-label">How many end users (persons) will need the SDK feature in your application?
                <span class="fontOrange">*</span></label>
              <div class="radio-group">
                <div class="radio">
                  <label class="radio">
                    <input name="CompanySize" id="CompanySize1" type="radio" value="Less than 30" required>
                    <label for="CompanySize1"><span>Less than 30</span></label>
                  </label>
                </div>
                <div class="radio">
                  <label class="radio">
                    <input name="CompanySize" id="CompanySize2" type="radio" value="31 - 100">
                    <label for="CompanySize2"><span>31 - 100</span></label>
                  </label>
                </div>
                <div class="radio">
                  <label class="radio">
                    <input name="CompanySize" id="CompanySize3" type="radio" value="101 - 500">
                    <label for="CompanySize3"><span>101 - 500</span></label>
                  </label>
                </div>
                <div class="radio">
                  <label class="radio">
                    <input name="CompanySize" id="CompanySize4" type="radio" value="501 - 1000">
                    <label for="CompanySize4"><span>501 - 1000</span></label>
                  </label>
                </div>
                <div class="radio">
                  <label class="radio">
                    <input name="CompanySize" id="CompanySize5" type="radio" value="More than 1000">
                    <label for="CompanySize5"><span>More than 1000</span></label>
                  </label>
                </div>
                <div class="radio">
                  <label class="radio">
                    <input name="CompanySize" id="CompanySize6" type="radio" value="I don't know">
                    <label for="CompanySize6"><span>I don't know</span></label>
                  </label>
                </div>
              </div>
            </div>
            <div class="form-group">
              <label class="control-label">So far, does our SDK meet your need well? <span
                  class="fontOrange">*</span></label>
              <div class="radio-group">
                <div class="radio">
                  <label class="radio">
                    <input name="CustomerReviews" id="CustomerReviews1" type="radio" value="Yes, I am satisfied."
                      required>
                    <label for="CustomerReviews1"><span>Yes, I am satisfied.</span></label>
                  </label>
                </div>
                <div class="radio">
                  <label class="radio">
                    <input name="CustomerReviews" id="CustomerReviews2" type="radio"
                      value="Yes, I just need more time to complete the development.">
                    <label for="CustomerReviews2"><span>Yes, I just need more time to complete the
                        development.</span></label>
                  </label>
                </div>
                <div class="radio">
                  <label class="radio">
                    <input name="CustomerReviews" id="CustomerReviews3" type="radio"
                      value="I haven't tried the SDK yet.">
                    <label for="CustomerReviews3"><span>I haven't tried the SDK yet.</span></label>
                  </label>
                </div>
                <div class="radio">
                  <label class="radio">
                    <input name="CustomerReviews" id="CustomerReviews4" type="radio"
                      value="No, I need some technical help.">
                    <label for="CustomerReviews4"><span>No, I need some technical help.</span></label>
                  </label>
                  <textarea id="MyTechnicalHelp" rows="2" name="MyTechnicalHelp" placeholder=""></textarea>
                </div>
              </div>
            </div>
          </div>
          <div class="survey survey2">
            <div class="form-group">
              <label class="control-label">Based on your current estimation, how soon will you release the application
                with the SDK features? <span class="fontOrange">*</span></label>
              <div class="radio-group">
                <div class="radio">
                  <label class="radio">
                    <input name="ReleaseTimeB" id="ReleaseTimeB1" type="radio" value="Less than a week" required>
                    <label for="ReleaseTimeB1"><span>Less than a week</span></label>
                  </label>
                </div>
                <div class="radio">
                  <label class="radio">
                    <input name="ReleaseTimeB" id="ReleaseTimeB2" type="radio" value="Less than a month">
                    <label for="ReleaseTimeB2"><span>Less than a month</span></label>
                  </label>
                </div>
                <div class="radio">
                  <label class="radio">
                    <input name="ReleaseTimeB" id="ReleaseTimeB3" type="radio" value="1 to 3 months">
                    <label for="ReleaseTimeB3"><span>1 to 3 months</span></label>
                  </label>
                </div>
                <div class="radio">
                  <label class="radio">
                    <input name="ReleaseTimeB" id="ReleaseTimeB4" type="radio" value="3 to 6 months">
                    <label for="ReleaseTimeB4"><span>3 to 6 months</span></label>
                  </label>
                </div>
                <div class="radio">
                  <label class="radio">
                    <input name="ReleaseTimeB" id="ReleaseTimeB5" type="radio" value="More than 6 months">
                    <label for="ReleaseTimeB5"><span>More than 6 months</span></label>
                  </label>
                </div>
              </div>
            </div>
            <div class="form-group">
              <label class="control-label">How has your experience been with the SDK during your trial period? <span
                  class="fontOrange">*</span></label>
              <div class="textarea-group">
                <textarea id="OtherInfo" rows="2" name="OtherRequiredOrSuggestion" placeholder=""></textarea>
              </div>
            </div>
          </div>
          <div class="submitSurvyLine">
            <span class="d-btn submit-btn fontOswald">Submit</span>
            <p>The license will be sent to your email immediately.</p>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

<script src="/webres/wwwroot/js/AesGcmHybridEncryptor.js"></script>
<script src="/webres/wwwroot/js/docs/trialLicense.js"></script>

> [!NOTE]
>
> - The license string above grants a time-limited free trial which requires a network connection.
> - You can request a 30-day trial license via the [Request a Trial License](https://www.dynamsoft.com/customer/license/trialLicense?product=mrz&utm_source=guide&package=react-native){:target="_blank"} link.

## Add the SDK

Run the following command from your React Native project root to add `dynamsoft-mrz-scanner-bundle-react-native` to the dependencies:

```bash
npm install dynamsoft-mrz-scanner-bundle-react-native@3.4.1310
```

For iOS, install the CocoaPods dependencies after the npm install completes. Run the following from the project root:

```bash
cd ios && bundle exec pod install --repo-update
```

## Building the MRZ Scanner Application

The following steps build the **ScanMRZ** sample app. You can also download the complete project from the [GitHub repo](https://github.com/Dynamsoft/mrz-scanner-mobile-react-native).

### Step 1: Create a New Project

Initialize a new React Native project:

```bash
npx @react-native-community/cli init ScanMRZ
```

Change into the new project directory — all remaining steps run from the project root:

```bash
cd ScanMRZ
```

The implementation in this guide lives in `src/App.tsx`. Create the `src` folder, move the generated `App.tsx` into it, and update `index.js` so the registered component resolves to `./src/App`:

```js
import App from './src/App';
```

### Step 2: Add the SDK

Follow the instructions in the [Add the SDK](#add-the-sdk) section above to add `dynamsoft-mrz-scanner-bundle-react-native` to your project.

### Step 3: Configure Platform Settings

Before the scanner can open the camera, both platforms need a small amount of configuration.

**iOS** — open `ios/ScanMRZ/Info.plist` and add a camera usage description. Without this the app will crash immediately when the scanner tries to open the camera:

```xml
<key>NSCameraUsageDescription</key>
<string>This app uses the camera to scan MRZ documents.</string>
```

**Android** — no manual permission changes are required. The SDK's manifest merges the `CAMERA` permission automatically. The trial license requires a network connection, so keep the `INTERNET` permission declared in `android/app/src/main/AndroidManifest.xml` (it is present by default in React Native templates):

```xml
<uses-permission android:name="android.permission.INTERNET" />
```

### Step 4: Set Up the UI

Create the initial Home screen with a single **Scan an MRZ** button anchored toward the bottom of the screen. Scan results will be rendered in the same component via conditional rendering, added in [Step 7](#step-7-display-the-results).

Replace the contents of `src/App.tsx` with the following:

```tsx
import React from 'react';
import {StyleSheet, Text, TouchableOpacity, View} from 'react-native';

function App(): React.JSX.Element {
  const ScanMRZ = async () => {
    // The scanner launch logic is added in Steps 5 and 6.
  };

  return (
    <View style={styles.idleContainer}>
      <TouchableOpacity style={styles.scanButton} onPress={ScanMRZ}>
        <Text style={styles.scanButtonText}>Scan an MRZ</Text>
      </TouchableOpacity>
    </View>
  );
}

const BG = '#000000';
const WHITE = '#ffffff';
const BTN_GREY = '#555555';

const styles = StyleSheet.create({
  idleContainer: {
    flex: 1,
    backgroundColor: BG,
    alignItems: 'center',
    justifyContent: 'flex-end',
    padding: 24,
    paddingBottom: 32,
  },
  scanButton: {
    backgroundColor: BTN_GREY,
    borderRadius: 8,
    paddingVertical: 14,
    paddingHorizontal: 48,
  },
  scanButtonText: {
    color: WHITE,
    fontSize: 16,
    fontWeight: '600',
  },
});

export default App;
```

### Step 5: Configure the Scanner

Import the SDK and create an `MRZScanConfig` inside the `ScanMRZ` function. The only required setting is the license key — see the [Licensing](#licensing) section above for how to obtain one. For the full list of optional settings such as document-type filtering, UI button visibility, and image-capture options, see the [Customize MRZ Scanner](https://www.dynamsoft.com/mrz-scanner/docs/mobile/programming/react-native/user-guide/customize-mrz-scanner.md) guide.

```tsx
/* Add to the import block at the top of App.tsx */
import {
  EnumResultStatus,
  MRZScanConfig,
  MRZScanner,
  MRZScanResult,
} from 'dynamsoft-mrz-scanner-bundle-react-native';

/* App.tsx — update the ScanMRZ function from Step 4 */
const ScanMRZ = async () => {
  const mrzScanConfig = {
    // Required: set a valid license key.
    license: 'DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9',
  } as MRZScanConfig;
};
```

### Step 6: Launch the Scanner

Add a `mrzScanResult` state variable, then call `MRZScanner.launch(config)` to open the scanner and await the result. Each result carries a `resultStatus` of `RS_FINISHED` (MRZ decoded), `RS_CANCELED` (user closed the scanner), or `RS_EXCEPTION` (an error occurred).

Continuing from Step 5:

```tsx
/* Update the React import to include useState */
import React, {useState} from 'react';

/* App.tsx — inside the App component, above the ScanMRZ declaration */
const [mrzScanResult, setMrzScanResult] = useState<MRZScanResult | null>(null);

/* App.tsx — update the ScanMRZ function from Step 5 */
const ScanMRZ = async () => {
  const mrzScanConfig = {
    license: 'DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9',
  } as MRZScanConfig;
  const mrzResult = await MRZScanner.launch(mrzScanConfig);
  setMrzScanResult(mrzResult);
};
```

> [!NOTE]
>
> - `mrzScanResult.data` holds the parsed MRZ fields (`firstName`, `lastName`, `dateOfBirth`, etc.). See the [MRZData API reference](https://www.dynamsoft.com/mrz-scanner/docs/mobile/programming/react-native/api-reference/mrz-data.md) for the full field list.
> - `mrzScanResult.portraitImage`, `mrzSideDocumentImage`, `oppositeSideDocumentImage`, `mrzSideOriginalImage`, and `oppositeSideOriginalImage` are `undefined` when the corresponding image option is disabled in `MRZScanConfig` or when no image was captured for that side.
> - `mrzSideDocumentImage` corresponds to the side of the document containing the machine-readable zone. `oppositeSideDocumentImage` refers to the reverse side, which is relevant for two-sided documents such as TD1 ID cards.

### Step 7: Display the Results

The `return` statement written in Step 4 only renders the idle Home screen. Now that `mrzScanResult` is populated after a scan, branch on `resultStatus` and render the appropriate view. `RS_CANCELED` shows a short hint, `RS_EXCEPTION` shows the error string, and `RS_FINISHED` shows the parsed fields and captured images.

Replace the single `return` block from Step 4 with the following conditional renders:

```tsx
/* Add Image and ScrollView to the react-native import */
import {Image, ScrollView, StyleSheet, Text, TouchableOpacity, View} from 'react-native';

/* App.tsx — replace the return block from Step 4 */
if (mrzScanResult == null) {
  return (
    <View style={styles.idleContainer}>
      <TouchableOpacity style={styles.scanButton} onPress={ScanMRZ}>
        <Text style={styles.scanButtonText}>Scan an MRZ</Text>
      </TouchableOpacity>
    </View>
  );
}

if (mrzScanResult.resultStatus === EnumResultStatus.RS_CANCELED) {
  return (
    <View style={styles.idleContainer}>
      <Text style={styles.idleHint}>Scan cancelled.</Text>
      <TouchableOpacity style={styles.scanButton} onPress={ScanMRZ}>
        <Text style={styles.scanButtonText}>Scan an MRZ</Text>
      </TouchableOpacity>
    </View>
  );
}

if (mrzScanResult.resultStatus === EnumResultStatus.RS_EXCEPTION) {
  return (
    <View style={styles.idleContainer}>
      <Text style={styles.errorText}>{mrzScanResult.errorString}</Text>
      <TouchableOpacity style={styles.scanButton} onPress={ScanMRZ}>
        <Text style={styles.scanButtonText}>Scan an MRZ</Text>
      </TouchableOpacity>
    </View>
  );
}

// resultStatus === EnumResultStatus.RS_FINISHED
const mrzData = mrzScanResult.data!;
const fullName = `${mrzData.firstName} ${mrzData.lastName}`;

return (
  <View style={styles.container}>
    <ScrollView contentContainerStyle={styles.scrollContent}>
      {/* Header: name, gender/age, expiry, portrait image */}
      <View style={styles.headerSection}>
        <View style={styles.headerTextBlock}>
          <Text style={styles.fullName}>{fullName}</Text>
          <Text style={styles.genderAge}>
            {mrzData.sex}, {mrzData.age} years old
          </Text>
          <Text style={styles.expiryShort}>Expiry: {mrzData.dateOfExpire}</Text>
        </View>
        <Image
          style={styles.portraitBox}
          source={mrzScanResult.portraitImage ?? require('./assets/ic_portrait_placeholder.jpg')}
          resizeMode="contain"
        />
      </View>

      {/* Personal Info */}
      <Text style={styles.sectionTitle}>Personal Info</Text>
      <Text style={styles.infoRow}>Given Name: {mrzData.firstName}</Text>
      <Text style={styles.infoRow}>Surname: {mrzData.lastName}</Text>
      <Text style={styles.infoRow}>Date of Birth: {mrzData.dateOfBirth}</Text>
      <Text style={styles.infoRow}>Nationality: {mrzData.nationalityRaw}</Text>

      {/* Document Info */}
      <Text style={styles.sectionTitle}>Document Info</Text>
      <Text style={styles.infoRow}>Doc. Number: {mrzData.documentNumber}</Text>
      <Text style={styles.infoRow}>Expiry Date: {mrzData.dateOfExpire}</Text>

      {/* Raw MRZ Text */}
      <Text style={styles.sectionTitle}>Raw MRZ Text</Text>
      <Text style={styles.rawMrz}>{mrzData.mrzText}</Text>
    </ScrollView>

    {/* Bottom re-scan button */}
    <View style={styles.bottomButtons}>
      <TouchableOpacity style={styles.bottomBtn} onPress={ScanMRZ}>
        <Text style={styles.bottomBtnText}>Scan an MRZ</Text>
      </TouchableOpacity>
    </View>
  </View>
);
```

Extend the `StyleSheet.create` block with styles for the new views (`container`, `scrollContent`, `headerSection`, `headerTextBlock`, `fullName`, `genderAge`, `expiryShort`, `portraitBox`, `sectionTitle`, `infoRow`, `rawMrz`, `idleHint`, `errorText`, `bottomButtons`, `bottomBtn`, `bottomBtnText`). For brevity, the full style definitions are omitted here — refer to [App.tsx in the ScanMRZ sample](https://github.com/Dynamsoft/mrz-scanner-mobile-react-native/src/App.tsx) for the complete implementation, which also includes a Processed/Original image switcher for the document images and a long-press-to-save-image action.

> [!NOTE]
>
> - When no portrait image is available, the sample falls back to a bundled placeholder at `./assets/ic_portrait_placeholder.jpg`. Add your own placeholder image and reference it with `require('./assets/your-placeholder.jpg')`.
> - For the complete set of fields on `MRZData`, see the [MRZData API reference](https://www.dynamsoft.com/mrz-scanner/docs/mobile/programming/react-native/api-reference/mrz-data.md).

### Step 8: Run the Project

Both platforms must be run on a physical device — the iOS simulator and most Android emulators do not expose a working camera to the SDK.

#### iOS

Before running, the developer signing must be configured:

1. Open `ios/ScanMRZ.xcworkspace` in Xcode.
2. Select the project, open the **Signing & Capabilities** tab, and set a valid **Team**. Without this the build will fail.

Connect a physical iOS device, then launch the app using either option below.

**Option A — Run from Xcode.** Select your connected device from the top bar and click **Run**.

**Option B — Run from the command line.** From the project root, target the device with the `--device` flag. Running `npm run ios` or `npx react-native run-ios` without this flag defaults to the simulator, which will not work for this sample:

```bash
npx react-native run-ios --device
```

If multiple devices are connected, pass the device name explicitly:

```bash
npx react-native run-ios --device "DEVICE-NAME"
```

> [!NOTE]
> If you try running the project on the iOS simulator, you will encounter errors as the scanner uses the device camera, which is unavailable on the simulator.

#### Android

Connect a physical Android device with USB debugging enabled, then run from the project root:

```bash
npm run android
```

You can list connected devices with `adb devices`.

## Next Steps

- **Samples** — Explore the complete [ScanMRZ sample on GitHub](https://github.com/Dynamsoft/mrz-scanner-mobile-react-native).
- **Customize** — Learn how to configure document type, UI elements, and feedback in the [Customize MRZ Scanner](https://www.dynamsoft.com/mrz-scanner/docs/mobile/programming/react-native/user-guide/customize-mrz-scanner.md) guide.
- **API Reference** — Browse the full [React Native API Reference](https://www.dynamsoft.com/mrz-scanner/docs/mobile/programming/react-native/api-reference/index.md) for all classes and methods.
- **Support** — Contact the [Dynamsoft Support Team](https://www.dynamsoft.com/contact) for help or custom requirements.