前置学习及实践成果 系统初步搭建

     

一、前置开发基础与核心优化目标

在 Day4~6 开发前,已完成React Native(以下简称 RN)环境配置VR 康复系统框架搭建,本阶段核心目标是完善系统交互体验与稳定性,具体实现:

  1. 为训练场景列表集成上拉加载 + 下拉刷新功能,支持数据增量加载与实时刷新;
  2. 覆盖全场景数据加载提示(加载中、加载失败、无更多数据、空数据),确保交互逻辑闭环,且提示样式适配鸿蒙多终端显示规范;
  3. 解决开发中遇到的平台适配、组件兼容、状态管理等关键报错,保障系统稳定运行

二、报错与处理

1、第三方库兼容性问题

问题现象

使用react-native-pull-to-refresh库实现下拉刷新时,报错 “无法解析模块./lib/PullToRefreshView”,原因是该库未适配鸿蒙模块解析规则,依赖特定平台模块导致兼容性失效。

解决方案

替换为 RN 原生RefreshControl组件(已兼容 OpenHarmony),该组件可直接嵌入ScrollViewFlatList,支持自定义加载颜色与刷新逻辑,代码示例:

报错代码

Error: Unable to resolve module ./lib/PullToRefreshView from D:\AtomGitRepo\AtomGitNews\node_modules\react-native-pull-to-refresh\index.js:

None of these files exist:
  * node_modules\react-native-pull-to-refresh\lib\PullToRefreshView(.harmony.js|.native.js|.js|...)

安装了与OpenHarmony不兼容的库,该库内部依赖特定平台模块,未适配OpenHarmony的模块解析规则。

于是,使用React Native原生RefreshControl(OpenHarmony兼容):

<ScrollView
  refreshControl={
    <RefreshControl
      refreshing={refreshing}
      onRefresh={handleRefresh}
      colors={['#1E88E5']}
    />
  }
>
  {/* 列表内容 */}
</ScrollView>

鸿蒙适配补充

  • 若需使用其他三方库,优先选择@react-native-oh-tpl/xxx前缀的鸿蒙补丁库(如@react-native-oh-tpl/react-native-gesture-handler),通过 “补丁化移植” 实现跨平台兼容(参考 360doc 个人图书馆方案);

  • 安装三方库后需检查oh-package.json5配置,确保指定@rnoh/react-native-openharmony版本(如 0.72.53),避免版本冲突。

2、平台差异导致的组件不可用

报错如下:使用 RN 原生Slider组件设置训练难度(1~5 级)时,报错 “Element type is invalid: got undefined”,原因是Slider在 OpenHarmony 上实现不完整,运行时无法解析。

Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined.

Slider 组件在OpenHarmony上的实现不完整,导致运行时解析为 undefined

问题出在下列代码:

// 使用OpenHarmony未完全支持的Slider组件
import { Slider } from 'react-native';

// 渲染Slider
<Slider
  style={styles.slider}
  minimumValue={1}
  maximumValue={5}
  value={difficulty}
  onValueChange={setDifficulty}
/>

我询问ai,并使用按钮组替代Slider,进行了如下更正:

<View style={styles.difficultyButtonsContainer}>
  {[1, 2, 3, 4, 5].map((level) => (
    <TouchableOpacity
      key={level}
      style={[styles.difficultyButton, difficulty === level && styles.difficultyButtonSelected]}
      onPress={() => setDifficulty(level)}
    >
      <Text style={[styles.difficultyButtonText, difficulty === level && styles.difficultyButtonTextSelected]}>
        {level}级
      </Text>
    </TouchableOpacity>
  ))}
</View>

3、异步操作未处理错误

出现如下问题:调用模拟 API 加载训练场景时,setLoading始终为true,界面卡住且无错误提示,原因是异步函数未捕获异常,导致setLoading(false)无法执行。

错误代码

const fetchScenes = async () => {
  setLoading(true);
  await simulateApiDelay(1500); // 模拟网络请求
  setScenes(mockScenes);
  setLoading(false);
};

解决方案:

通过try-catch-finally完善错误处理,确保 “加载状态” 无论成功 / 失败都能正常关闭,同时添加错误提示

const fetchScenes = async () => {
  try {
    setLoading(true);
    setError(null); // 重置错误状态
    await simulateApiDelay(1500);
    setScenes(mockScenes);
  } catch (err) {
    setError('加载失败,请重试'); // 显示错误信息
    console.error('Failed to fetch scenes:', err);
  } finally {
    setLoading(false); // 无论成功失败都关闭加载状态
  }
};

4、状态更新逻辑错误

实现上拉加载更多场景时,报错如下,

Warning: Cannot update a component's state while rendering a different component.

原因是直接修改useState返回的状态变量(loadingMore = true),未通过set函数更新,导致状态不触发重新渲染。直接修改 useState 返回的状态变量,而不是使用 set 函数,导致状态更新无效

// 错误:直接修改状态
const handleLoadMore = () => {
  if (hasMore && !loadingMore) {
    loadingMore = true; // 错误:直接赋值,不会触发重新渲染
    fetchMoreScenes();
  }
};

通过如下方式修改代码实现了改正:

import { useState } from 'react-native';

const LoadMoreScenes = () => {
  const [hasMore, setHasMore] = useState(true); // 是否有更多数据
  const [loadingMore, setLoadingMore] = useState(false); // 加载更多状态
  const [scenes, setScenes] = useState([]);

  // 加载更多逻辑
  const fetchMoreScenes = async () => {
    await simulateApiDelay(1000);
    const newScenes = [/* 新场景数据 */];
    setScenes(prev => [...prev, ...newScenes]); // 增量更新数据
    setLoadingMore(false);
    if (newScenes.length === 0) setHasMore(false); // 无更多数据时更新状态
  };

  // 处理上拉加载触发
  const handleLoadMore = () => {
    // 仅当“有更多数据”且“未在加载中”时触发
    if (hasMore && !loadingMore) {
      setLoadingMore(true); // 正确:使用set函数更新状态
      fetchMoreScenes();
    }
  };

  return (
    <View>
      {/* 场景列表 */}
      {loadingMore && <Text>加载更多...</Text>}
      {!hasMore && <Text>没有更多数据了</Text>}
      {/* 上拉加载触发区域(如FlatList的onEndReached) */}
    </View>
  );
};

三、实现效果

选择场景

下拉刷新

上拉加载

训练入口:

1. 核心功能效果

功能模块 实现效果
下拉刷新 触发后显示蓝色加载指示器,刷新完成后更新场景列表数据
上拉加载 滑动到底部时加载更多场景,无数据时显示 “没有更多数据了” 提示
难度选择 5 个按钮对应 1~5 级难度,选中态高亮显示,点击可切换
实时数据展示 训练界面显示 “动作正确率(90%)”“运动范围(90°)”“心率(75 BPM)” 等数据
场景选择 支持医院康复中心(室内)、公园(户外)、个性化自定义场所 3 类训练环境选择

2. 当前系统局限(待优化)

  • 未实现用户登录 / 登出功能,导致训练数据无法关联用户身份,无法持久化存储;

  • 设备接入功能未完成,无法连接 VR 设备获取实时动作数据;

  • 排行榜统计、AI 洞察分析等功能处于待开发状态,需后续补充接口与逻辑。

       用户输入信息后才可进行数据反馈,登入/登出,目前无法完成训练数据收集、设备接入、排行榜统计等功能,系统后续仍在完善。

四、总结归纳

1、鸿蒙适配能力:掌握 RN 三方库鸿蒙适配方案(优先原生组件、使用补丁库)、平台差异组件替代策略,解决了库兼容性、组件不可用等核心问题;

2、状态管理规范:熟练使用useState(通过set函数更新)、useEffect(生命周期管理),结合try-catch-finally处理异步状态,避免界面卡死与报错;

3、用户体验优化:覆盖加载中、加载失败、空数据等全场景提示,通过按钮组、颜色区分等设计提升交互友好性;

4、模拟 API 与测试:实现 API 延迟模拟,便于测试不同加载状态下的界面表现,为后续对接真实接口打下基础;

5、代码结构化:将难度选择、场景加载等逻辑拆分为独立组件 / 函数,提升代码可维护性,符合模块化开发规范。

欢迎加入开源鸿蒙跨平台社区:
https://openharmonycrossplatform.csdn.net

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐