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

React Native Expo项目中如何从Firebase获取并展示存储的图片

错误原因
  • 混淆了函数组件useState和类组件this.state的用法:你在函数组件中用useState存储状态,却用this.state.profileImageUrl读取变量,该变量不存在所以直接报错。
  • 状态变量和组件重名:存储图片的状态变量命名为Image,和React Native原生的Image组件重名,会引发渲染异常。
  • 存储url的逻辑错误:调用setImage时将实际url变量套了引号变成了固定字符串'url',且存储的key为profileimageUrl(全小写开头),读取时用的是驼峰命名profileImageUrl,大小写不一致无法正常取值。
  • 上传逻辑没有持久化存储url:上传完成后仅打印了url,没有存储到全局状态、本地存储等可跨页面访问的位置,第二个页面无法直接拿到上传后的地址。
  • Image组件属性写法错误:source属性需要传入{uri: 图片链接}格式的对象,不能直接填入url字符串。
  • 获取url的逻辑没有放在生命周期钩子中:直接写在组件顶层会在每次组件渲染时重复执行,需要放在useEffect中限制仅挂载时执行一次。
修复代码

上传逻辑修改

// 需先安装@react-native-async-storage/async-storage用于跨页面存地址
import AsyncStorage from '@react-native-async-storage/async-storage';

const uploadImage = async () => {
  const blob = await new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.onload = function () {
      resolve(xhr.response);
    };
    xhr.onerror = function () { // 修复原代码的拼写错误oneerror -> onerror
      reject(new TypeError('Network request failed'));
    };
    xhr.responseType = 'blob';
    xhr.open('GET', image, true);
    xhr.send(null);
  });

  // 文件名添加时间戳避免多次上传覆盖同一文件
  const ref = firebase.storage().ref().child(`/ankit/${Date.now()}.jpg`);
  const snapshot = ref.put(blob);

  snapshot.on(
    firebase.storage.TaskEvent.STATE_CHANGED,
    () => {
      setUploading(true);
    },
    (error) => {
      setUploading(false);
      console.log(error);
      blob.close();
    },
    async () => {
      const url = await snapshot.snapshot.ref.getDownloadURL();
      setUploading(false);
      console.log('download url', url);
      // 将上传后的url存在本地存储,供第二个页面读取
      await AsyncStorage.setItem('profileImageUrl', url);
    }
  );
};

第二页展示逻辑修改

import { useEffect, useState } from 'react';
import { View, Image } from 'react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';

const SecondPage = () => {
  // 单独定义状态存储图片url,避免和组件重名
  const [profileImageUrl, setProfileImageUrl] = useState(null);

  useEffect(() => {
    // 从本地存储读取之前上传的图片地址
    const getSavedImage = async () => {
      const savedUrl = await AsyncStorage.getItem('profileImageUrl');
      if (savedUrl) setProfileImageUrl(savedUrl);
    };
    getSavedImage();
    
    // 如果你需要直接从Firebase拉取固定路径的文件,用下面的逻辑,注意路径要和上传的路径完全一致
    /*
    const imageRef = firebase.storage().ref('/ankit/你的具体文件名.jpg');
    imageRef.getDownloadURL()
      .then(url => setProfileImageUrl(url))
      .catch(e => console.log('获取图片地址失败:', e))
    */
  }, []);

  return (
    <View>
      {/* 判空后再渲染图片,避免加载报错,必须指定宽高才能正常显示网络图片 */}
      {profileImageUrl && (
        <Image 
          source={{ uri: profileImageUrl }} 
          style={{ width: 200, height: 200 }} 
        />
      )}
    </View>
  );
};

export default SecondPage;

内容的提问来源于stack exchange,提问作者Ankit Verma

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 15:09:01