Command Palette

Search for a command to run...

Hướng dẫn viết Native Module trong React Native với Expo Modules API

Hướng dẫn viết Native Module trong React Native với Expo Modules API

Ở bài trước, bạn đã biết cách thoát khỏi chiếc vỏ bọc Expo Go và sử dụng Development Build để cài đặt bất kỳ thư viện Native nào trên mạng. Nhờ đó, ứng dụng của bạn không còn bị giới hạn bởi những gì Expo cung cấp sẵn nữa.

Nhưng hãy tưởng tượng một kịch bản khắc nghiệt hơn: Công ty của bạn vừa mua một chiếc máy in hóa đơn Bluetooth đặc chủng, hoặc đối tác giao cho bạn một bộ thư viện (SDK) nội bộ chuyên dùng để quét thẻ từ. Bạn lên mạng tìm kiếm mỏi mắt nhưng không có bất kỳ ai viết sẵn thư viện React Native cho thiết bị này cả!

Lúc này, bạn không thể tải bằng npm install được nữa. Bạn phải tự mình đóng vai người viết thư viện. Bằng cách nào? Chào mừng bạn đến với thế giới của Native Modules và cuộc cách mạng mang tên Expo Modules API.

1. Native Module là gì? Nỗi đau của "Kỷ nguyên cũ"

Native Module hiểu đơn giản là một "cây cầu" giúp code JavaScript (trong React Native) có thể gọi và điều khiển trực tiếp các đoạn code Native (Java/Kotlin trên Android và Objective-C/Swift trên iOS).

Native Module là gì?

Trong nhiều năm, việc tự viết một cây cầu như vậy trong React Native thuần (CLI) được coi là một "cơn ác mộng" với các lập trình viên frontend:

  • Bạn phải học những cú pháp C++ và Objective-C cổ lỗ sĩ cực kỳ rắc rối.
  • Bạn phải nhớ hàng chục macro (như RCT_EXPORT_METHOD) dài ngoằng.
  • Bạn phải mở Android Studio và Xcode lên, cấu hình thủ công từng file cấu trúc rất dễ sinh lỗi.

Chính vì sự phức tạp này, 90% lập trình viên React Native thường "đầu hàng" và đẩy việc này cho các kỹ sư Native chuyên trách.

2. Kỷ nguyên mới: Phép màu của Expo Modules API

Đội ngũ Expo một lần nữa xuất hiện và thay đổi luật chơi với Expo Modules API. Khung làm việc này định nghĩa lại hoàn toàn cách chúng ta viết code Native.

Expo Modules API

Sự vượt trội của Expo Modules API:

  1. Dùng ngôn ngữ hiện đại: Bạn được viết 100% bằng Swift (cho iOS) và Kotlin (cho Android) - đây là 2 ngôn ngữ hiện đại, cú pháp sạch sẽ và rất dễ học (đặc biệt nếu bạn đã biết JavaScript/TypeScript).
  2. Cú pháp "như ngôn ngữ loài người": Không còn các macro khó hiểu. Expo cung cấp một bộ công cụ (DSL - Domain Specific Language) giúp khai báo hàm Native cực kỳ tự nhiên.
  3. Tự động hóa hoàn toàn: Hệ thống tự động tạo cấu trúc thư mục, tự động liên kết (autolinking) mã Native của bạn vào dự án React Native. Bạn chỉ việc tập trung gõ code logic.

3. Khởi tạo Native Module đầu tiên

Hãy bắt tay vào làm một module cực kỳ đơn giản: Một hàm trả về tên dòng máy điện thoại và một câu chào mừng.

Thay vì phải tự mò mẫm tạo file, Expo cung cấp sẵn một công cụ tạo thư mục module chuẩn mực. Mở Terminal và gõ:

npx create-expo-module my-custom-module

Hệ thống sẽ đặt cho bạn vài câu hỏi (như tên thư viện, tác giả), sau đó nó sẽ sinh ra một thư mục my-custom-module chứa cấu trúc sau:

  • 📁 android/src/main/java/... (Nơi viết code Kotlin)
  • 📁 ios/ (Nơi viết code Swift)
  • 📁 src/ (Nơi viết code TypeScript/JavaScript để gọi 2 file trên)

4. Mổ xẻ code: Từ code Native đến code JavaScript

Hãy cùng xem Expo Modules API đã làm cho việc giao tiếp này trở nên dễ dàng như thế nào!

Bước 1: Viết mã iOS (Swift)

Mở file ios/MyCustomModule.swift. Cú pháp cốt lõi xoay quanh khối Module().

import ExpoModulesCore

public class MyCustomModule: Module {
  public func definition() -> ModuleDefinition {
    // 1. Tên của thư viện khi gọi từ JavaScript
    Name("MyCustomModule")

    // 2. Viết một hàm tên là "sayHello" để JS gọi xuống
    Function("sayHello") { (name: String) -> String in
      return "Xin chào \(name)! Đây là lời chào từ tận lõi iOS Swift."
    }

    // 3. Bạn cũng có thể bắt các sự kiện, lấy phần cứng thiết bị ở đây
  }
}

Bước 2: Viết mã Android (Kotlin)

Mở file android/src/main/java/.../MyCustomModule.kt. Bạn sẽ thấy cú pháp gần như y hệt Swift! Đây là nỗ lực tuyệt vời của Expo nhằm đồng nhất trải nghiệm lập trình.

package expo.modules.mycustommodule

import expo.modules.kotlin.modules.Module
import expo.modules.kotlin.modules.ModuleDefinition

class MyCustomModule : Module() {
  override fun definition() = ModuleDefinition {
    // 1. Tên thư viện
    Name("MyCustomModule")

    // 2. Viết hàm tên là "sayHello" để JS gọi xuống
    Function("sayHello") { name: String ->
      "Xin chào $name! Đây là lời chào từ tận lõi Android Kotlin."
    }
  }
}

Bước 3: Gọi hàm ở trên Giao diện (JavaScript)

Bây giờ, hãy quay lại thế giới của chúng ta. Bạn mở file src/index.ts và thiết lập kết nối:

// Gọi hàm từ lõi Native lên
import MyCustomModule from './MyCustomModule'

export function sayHello(name: string): string {
  // Chỉ việc gọi hàm như một function bình thường!
  return MyCustomModule.sayHello(name)
}

Và ở file Giao diện React Native (App.tsx), bạn sử dụng nó vô cùng nhẹ nhàng:

import { Text, View } from 'react-native'
import { sayHello } from 'my-custom-module'

export default function App() {
  const greeting = sayHello('Lập trình viên')

  return (
    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
      {/* Trên iOS sẽ in ra dòng chữ của Swift, trên Android sẽ in dòng chữ của Kotlin */}
      <Text style={{ fontSize: 18, color: 'blue' }}>{greeting}</Text>
    </View>
  )
}

Tuyệt vời chưa? Hoàn toàn không có những cấu hình rườm rà. Bạn truyền một chuỗi string từ JS, Native bắt lấy, xử lý, và trả về kết quả mượt mà, đồng bộ và cực kỳ nhanh chóng.

5. Khi nào thực sự cần viết Native Module?

Việc tự viết Native Module là một vũ khí hạng nặng. Bạn chỉ nên "rút kiếm" trong các trường hợp sau:

  1. Giao tiếp với phần cứng đặc thù: Máy in nhiệt, máy POS quẹt thẻ, cân điện tử kết nối Bluetooth,...
  2. Tích hợp SDK bên thứ ba: Đối tác cung cấp cho bạn thư viện gốc bằng file .framework (iOS) hoặc .aar (Android) nhưng chưa hỗ trợ React Native.
  3. Tối ưu hiệu năng cực độ: Các tác vụ xử lý hình ảnh phức tạp, nén video, mã hóa file nặng cần tận dụng sức mạnh đa nhân CPU (xử lý đa luồng).

Kết luận: Expo Modules API đã phá vỡ mọi rào cản

Expo Modules API đã phá vỡ rào cản sợ hãi của các lập trình viên Frontend khi phải đối mặt với mã nguồn Native. Nó giúp bạn dễ dàng viết Swift và Kotlin, đóng gói chúng thành một thư viện xịn xò và gọi nó ra bằng JavaScript.

Đến đây, bạn đã chính thức nắm giữ toàn bộ "bí kíp võ công" từ cơ bản đến cảnh giới cao nhất của React Native và Expo. Bạn có thể xây dựng giao diện, quản lý dữ liệu, điều hướng mượt mà, gọi API và thậm chí can thiệp thẳng vào hệ điều hành!

Nhưng, một ứng dụng tuyệt vời vẫn sẽ vô hình nếu nó chỉ nằm trên máy tính của bạn. Ở những bài học cuối cùng của series, chúng ta sẽ bắt tay vào công đoạn quan trọng nhất: Testing & Publishing, hẹn sớm được gặp lại bạn!

Bài viết liên quan

Hướng dẫn cài đặt môi trường React Native & Expo trong 15 phút

Bạn sợ cài đặt môi trường lập trình mobile phức tạp? Hướng dẫn chi tiết cách dùng Expo Go, Node.js để chạy app React Native ngay lập tức.

Hướng dẫn Unit Test trong React Native với Jest & Testing Library

Hướng dẫn chi tiết cách viết Unit Test trong dự án React Native. Nắm vững cách sử dụng Jest và React Native Testing Library để kiểm tra logic hàm và giả lập tương tác UI.

Tối ưu việc gọi API trong React Native bằng React Query

Hướng dẫn tối ưu hóa luồng gọi API trong React Native với TanStack Query. Khám phá cách sử dụng useQuery để quản lý Server State, tạo bộ nhớ đệm (cache) tự động siêu mượt.

Hướng dẫn tích hợp Push Notifications với React Native và Expo

Hướng dẫn chi tiết cách cài đặt và cấu hình Push Notifications trong React Native sử dụng hệ thống Expo. Nắm vững cách xin quyền, lấy Token và gửi thông báo kiểm thử.