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
相关产品推荐
相关产品推荐

