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

使用Hermes引擎时expo-image-picker报错及Firestore图片URI存为null求助

解决Expo ImagePicker + Hermes模块找不到及图片URI存Firestore问题

一、先修复「Cannot find native module 'ExponentImagePicker'」错误

该错误源于Expo 44版本中Hermes引擎与expo-image-picker的缓存/版本兼容问题,按以下步骤处理:

  1. 确保依赖版本匹配
    使用Expo官方安装命令,保证模块版本与Expo SDK 44完全兼容:
expo install expo-image-picker
  1. 清除缓存重启项目
    缓存残留会导致模块识别异常,执行:
expo r -c
  1. 确认导入方式正确
    自定义ImagePicker组件中,必须使用官方正确的导入路径:
import * as ImagePicker from 'expo-image-picker';
  1. 检查Hermes配置(可选)
    若项目明确启用Hermes,确保app.json配置正确:
{
  "expo": {
    "jsEngine": "hermes"
  }
}

二、实现图片URI传递与Firestore存储

当前PlaceForm与ImagePicker组件无数据交互,导致图片URI无法传递到父组件提交到Firestore,按以下步骤修改:

1. 修改PlaceForm组件,添加图片状态与提交逻辑

import { useState } from "react";
import { ScrollView, StyleSheet, Text, TextInput, View, Button, Alert } from "react-native";
import { Colors } from "../../constants/colors";
import ImagePicker from "./ImagePicker";
import firestore from '@react-native-firebase/firestore';

function PlaceForm(){
    const [enteredTitle, setEnteredTitle] = useState('');
    const [selectedImageUri, setSelectedImageUri] = useState(null); // 新增图片URI状态

    function changeTitleHandler(enteredText){
        setEnteredTitle(enteredText);
    }

    // 新增Firestore提交函数
    const submitToFirestore = async () => {
        if (!enteredTitle.trim() || !selectedImageUri) {
            Alert.alert('提示', '请填写标题并选择图片');
            return;
        }

        try {
            await firestore().collection('places').add({
                title: enteredTitle,
                imageUri: selectedImageUri,
                createdAt: firestore.FieldValue.serverTimestamp()
            });
            // 重置表单
            setEnteredTitle('');
            setSelectedImageUri(null);
            Alert.alert('成功', '数据已保存到Firestore');
        } catch (err) {
            console.error('保存失败:', err);
            Alert.alert('错误', '保存数据失败,请重试');
        }
    };

    return(
        <ScrollView style={styles.form}>
            <View>
                <Text style={styles.label}>Title</Text>
                <TextInput style={styles.input} onChangeText={changeTitleHandler} value={enteredTitle}/>
            </View>
            {/* 传递回调接收图片URI */}
            <ImagePicker onImageSelect={setSelectedImageUri} />
            {/* 添加提交按钮 */}
            <Button title="提交" onPress={submitToFirestore} style={{marginTop: 16}} />
        </ScrollView>
    )
}
export default PlaceForm;

const styles = StyleSheet.create({
    form :{
        flex: 1,
        padding:24,
    },
    label:{
        fontWeight:'bold',
        marginBottom:4,
        color: Colors.primary500
    },
    input:{
        marginBottom:8,
        paddingHorizontal:4,
        paddingVertical:8,
        fontSize:16,
        borderBottomColor:Colors.primary700,
        borderBottomWidth:2,
        backgroundColor: Colors.primary100
    }
})

2. 完善ImagePicker组件,实现图片选择与回调传递

import { useState } from 'react';
import { Button, View, Image, StyleSheet, Alert } from 'react-native';
import * as ImagePicker from 'expo-image-picker';

export default function ImagePicker({ onImageSelect }) {
    const [localImageUri, setLocalImageUri] = useState(null);

    // 申请相册权限
    const requestPermission = async () => {
        const { status } = await ImagePicker.requestMediaLibraryPermissionsAsync();
        if (status !== 'granted') {
            Alert.alert('权限不足', '需要允许访问相册才能选择图片');
            return false;
        }
        return true;
    };

    // 图片选择逻辑
    const pickImage = async () => {
        const hasPermission = await requestPermission();
        if (!hasPermission) return;

        const result = await ImagePicker.launchImageLibraryAsync({
            mediaTypes: ImagePicker.MediaTypeOptions.Images,
            allowsEditing: true,
            aspect: [4, 3],
            quality: 0.7,
        });

        // Expo 44返回结构为assets数组,取第一个元素的uri
        if (!result.canceled) {
            const imageUri = result.assets[0].uri;
            setLocalImageUri(imageUri);
            onImageSelect(imageUri); // 传递URI给父组件
        }
    };

    return (
        <View style={styles.container}>
            <Button title="选择图片" onPress={pickImage} />
            {/* 预览选中图片 */}
            {localImageUri && (
                <Image source={{ uri: localImageUri }} style={styles.previewImage} />
            )}
        </View>
    );
}

const styles = StyleSheet.create({
    container: {
        marginVertical: 16,
        alignItems: 'center',
    },
    previewImage: {
        width: 200,
        height: 150,
        marginTop: 12,
        borderRadius: 8,
        backgroundColor: '#f0f0f0',
    },
});

三、验证流程

  1. 重启项目后,点击「选择图片」,确认权限申请正常,能选择并预览图片
  2. 填写标题后点击「提交」,检查Firestore的places集合中是否存在包含imageUri字段的文档

内容的提问来源于stack exchange,提问作者Ravi Mishra

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 03:36:11