You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native使用expo-media-library展示相机胶卷图片文件名列表

问题根因

你遇到的报错本质是直接在React组件顶层执行异步逻辑,把async函数返回的Promise对象当成了React节点渲染,报错中带{_U, _V, _W, _X}的对象是JS内部存储Promise状态的私有字段,和你处理assets数据的逻辑无关。你控制台能打印到正常的文件名数组,是因为await执行完成后才触发打印,但React组件渲染时不会等待异步逻辑执行完毕,直接拿到Promise对象渲染才触发报错。

解决方案

1. 调整组件逻辑

不要将组件声明为async函数,也不要在组件顶层直接写await,所有异步获取资源的逻辑放到useEffect钩子中执行,获取到的数据存在useState中再渲染,同时不要漏掉expo-media-library必需的媒体库权限申请逻辑。
完整示例代码:

import { useState, useEffect } from 'react';
import { View, Text, Image } from 'react-native';
import * as MediaLibrary from 'expo-media-library';

export default function CameraRollScreen() {
  // 存储资源列表
  const [assets, setAssets] = useState([]);
  // 存储权限状态
  const [permissionGranted, setPermissionGranted] = useState(false);

  // 申请媒体库访问权限
  const requestPermission = async () => {
    const { status } = await MediaLibrary.requestPermissionsAsync();
    setPermissionGranted(status === 'granted');
  };

  // 获取相机胶卷资源
  const getCameraRollAssets = async () => {
    if (!permissionGranted) return;
    const recentCameraRoll = await MediaLibrary.getAssetsAsync({ first: 10 });
    setAssets(recentCameraRoll.assets);
  };

  // 组件挂载时申请权限
  useEffect(() => {
    requestPermission();
  }, []);

  // 权限通过后获取资源
  useEffect(() => {
    if (permissionGranted) {
      getCameraRollAssets();
    }
  }, [permissionGranted]);

  // 权限未通过时的占位UI
  if (!permissionGranted) {
    return (
      <View>
        <Text>未获得媒体库访问权限</Text>
      </View>
    );
  }

  // 渲染文件名列表
  return (
    <View>
      {assets.map(file => (
        <Text key={file.id}>{file.filename}</Text>
      ))}
    </View>
  );
}

2. 优化点说明

  • 你原代码中Object.values(files)是冗余逻辑,getAssetsAsync返回的assets本身就是数组,直接map即可
  • 列表的key建议用file.id而不是filename,避免出现重名文件导致渲染异常

渲染图片的实现方法

expo-media-library返回的asset对象自带uri字段,可以直接传给React Native的Image组件作为数据源,替换渲染部分的代码即可:

return (
  <View style={{ flex: 1, flexDirection: 'row', flexWrap: 'wrap' }}>
    {assets.map(file => (
      <Image
        key={file.id}
        source={{ uri: file.uri }}
        style={{ width: 100, height: 100, margin: 2 }}
        resizeMode="cover"
      />
    ))}
  </View>
);

内容的提问来源于stack exchange,提问作者Oliver Darby

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 16:18:03