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

使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 06:18:22