Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Native:用 React Native 渲染同一棵组件树

Native 不使用 DOM、AntD 或 Fluent UI。它使用 React Native 控件,但实体、OakComponent、projection、oakPath、关系路径和 execute 层级全部复用。

1. 添加 Native workspace

npx oak-cli add rn native
npm install

当前 CLI 会生成:

npm run start:native:native
npm run build:native:native:android
npm run build:native:native:ios
npm run run:android:native
npm run run:ios:native

工作区包含 Android、iOS、Metro、路由、polyfill 和 Oak 初始化代码。

2. 开发环境

Android 需要:

  • JDK;
  • Android Studio 与 SDK;
  • ANDROID_HOME,或 native/android/local.properties 中的 sdk.dir
  • 模拟器或开启 USB 调试的设备。

local.properties、签名 keystore、token 和密码不能提交。教程项目也不提交 debug.keystore

3. Native render 文件

为页面和共享组件增加:

render.native.tsx
render.native.scss

例如 GroupPanel:

import React from 'react';
import TodoList from '@project/components/todo/list';

export default function Render(props) {
    const { oakFullpath } = props.data;
    return oakFullpath ? (
        <TodoList oakPath={`${oakFullpath}.todo$group`} />
    ) : null;
}

这与 Web/Desktop 的关系挂载完全相同。

4. Group tabs 与 Modal

使用 React Native 控件:

import {
    Modal,
    Pressable,
    SafeAreaView,
    ScrollView,
    Text,
    View,
} from 'react-native';

横向 ScrollView 渲染 Group tabs。选择后挂载:

<GroupPanel oakPath={`${oakFullpath}.${selectedGroupId}`} />

Modal 中挂载 GroupUpsert。取消调用父节点 clean(),保存调用父 Group ListNode 的 execute()

5. Native Upsert

Group 使用 TextInput

<TextInput
    value={name}
    onChangeText={setName}
/>

Todo 使用 TextInputSwitch

<TextInput value={title} onChangeText={setTitle} />
<Switch value={completed} onValueChange={setCompleted} />

这些 setter 定义在共享 index.ts,内部调用 this.update(...)。render 只负责平台交互。

6. TodoList 的关系提交

TodoList Native render 仍通过:

<TodoUpsert oakPath={`${oakFullpath}.${editingTodoId}`} />

保存调用共享 saveTodo(),执行父 Group path,从而让 todo$group 级联绑定 groupId。不要在 Native render 中单独构造 operation。

7. 为什么不能用裸 tsc 判断 render props

Oak render 的 props 由 Oak 编译器注入。直接执行:

npx tsc -p native/tsconfig.json --noEmit

可能把 function Render(props) 报成隐式类型,因为这条命令绕过了 Oak render transform。项目级检查使用:

npm run build

Native 打包使用 Oak CLI 或 Metro。

8. 构建

完整 Android production build:

npm run build:native:native:android

它会生成路由、执行原生依赖 codegen、Metro bundle 和 Gradle release 构建。

如果当前机器没有 Android SDK,可先验证 JS/render 链路:

cd native
npx cross-env NODE_ENV=production OAK_PLATFORM=native react-native bundle \
  --entry-file=index.js \
  --bundle-output=../node_modules/.cache/oak-tutorial/native/index.android.bundle \
  --assets-dest=../node_modules/.cache/oak-tutorial/native/assets \
  --dev=false \
  --platform=android

看到 Done writing bundle outputDone copying assets,说明路由、Oak transform、Native render、Sass 与 JS 依赖已成功打包。它不能代替最终 APK 构建,但能把“代码问题”和“本机 SDK 问题”分开。

9. 验证

  1. Group tabs 可以横向滚动和切换;
  2. Group/Todo Modal Upsert 可新增和编辑;
  3. Todo 保存后关联正确 Group;
  4. 重启 App 后数据仍存在;
  5. Android cleartext/network 配置与 Oak access 地址一致;
  6. Git 中没有 local.properties、keystore 或 bundle 产物。
git add .
git commit -m "feat: add grouped Todo Native workspace"