使用AsyncStorage取值调用getThumbnailAsync报类型错误如何解决
问题根因
报错本质是传入VideoThumbnails.getThumbnailAsync的第一个参数不是预期的字符串类型,在安卓原生层被识别为HashMap对象,具体触发逻辑有两点:
- 状态初始值类型错误:你给
videoUri设置的初始值是空对象{},且在组件函数顶层直接调用异步的getData方法,组件挂载时会先执行挂载阶段的useEffect触发generateThumbnail,此时AsyncStorage的异步读取还没完成,传入的参数就是初始的空对象,直接触发类型不匹配错误。 - 触发时机错误:生成缩略图的useEffect没有依赖
videoUri状态,就算后续AsyncStorage读取到了正确的URI,也不会重新触发生成逻辑。如果之前写入AsyncStorage时没有把对象序列化为字符串,直接存入了对象结构,读取后的值也会是对象而非字符串,同样会触发该报错。
修复方法
按照以下几点调整代码即可:
- 将
videoUri的初始值从空对象改为空字符串,匹配URI的字符串类型预期 - 把AsyncStorage读取逻辑放到挂载时执行的useEffect中,避免组件每次重渲染都重复执行读取操作
- 调整缩略图生成的触发时机:给生成缩略图的useEffect添加
videoUri依赖,只有读取到有效非空的URI字符串后,才执行生成逻辑 - 增加读取值的类型校验,兼容之前可能错误存入对象的场景
修复后的完整代码:
import React, { useState, useEffect } from 'react'; import { View, Image } from 'react-native'; import AsyncStorage from '@react-native-async-storage/async-storage'; import * as VideoThumbnails from 'expo-video-thumbnails'; export default function ThumbnailsScreen() { // 初始值改为空字符串,符合URI类型要求 const [videoUri, setVideoUri] = useState(''); const [image, setImage] = useState(null); // 组件挂载时读取存储的视频URI useEffect(() => { const getData = async () => { try { const value = await AsyncStorage.getItem('@lastRecordedVideo'); if (value !== null) { // 校验值类型,兼容误存对象的情况 const validUri = typeof value === 'string' ? value : JSON.parse(value)?.uri; setVideoUri(validUri); } } catch(e) { console.log('读取视频URI失败:', e); } }; getData(); }, []); // 拿到有效URI后自动生成缩略图 useEffect(() => { if (!videoUri) return; const generateThumbnail = async () => { try { const { uri: thumbUri } = await VideoThumbnails.getThumbnailAsync( videoUri, { time: 1000 } ); setImage(thumbUri); } catch (e) { console.warn('生成缩略图失败:', e); } }; generateThumbnail(); }, [videoUri]); return ( <View> {image && <Image source={{ uri: image }} style={{ width: 300, height: 200 }} />} </View> ); }
额外注意:后续往AsyncStorage写入视频URI时,如果要存的是对象结构,必须先用JSON.stringify()转成字符串再存入,读取时对应用JSON.parse()解析,符合AsyncStorage只能存储字符串的API要求。
内容的提问来源于stack exchange,提问作者Renie
相关产品推荐
相关产品推荐

