从 firebase 存储调用图像 - 挂钩调用无效。钩子只能在函数组件的内部调用

Calling images from firebase storage - Invalid hook call. Hooks can only be called inside of the body of a function component

大家好!

我正在尝试制作一个可用于从 firebase 存储中调用图像的自定义挂钩。函数的输入来自包含 JSON 的 DATA.js 文件。例如 useImageSource(item.photo) - item.photo 将等于“lowerbody/forward-legswing”(这是我的 firebase 存储中到该锻炼图像的文件结构)。希望当我向您展示我的代码时它更有意义!哈!

useImageSource

下面是我为此制作的自定义挂钩的示例:

import React, { useState, useEffect } from "react";

import firebase from "@react-native-firebase/app";
import "@react-native-firebase/storage";
import FastImage from "react-native-fast-image";

import { getIllustration, Images } from "@flexeee:assets/images/Images";

export default function useImageSource(image, defaultImage) {
  const storage = firebase.storage();
  const [imageSource, setImageSource] = useState();

  useEffect(() => {
    async function getImageSource() {
      try {
        const url = await storage.ref(`images/${image}.png`).getDownloadURL();
        setImageSource({
          uri: url,
          priority: FastImage.priority.normal,
        });
      } catch (err) {
        setImageSource(defaultImage ?? Images.upperBody);
      }
    }

    getImageSource();
  }, [image, defaultImage, storage]);

  return imageSource;
}

子类别

这里是我尝试实现这个 useImageSource 挂钩的地方的示例:

import React, { useState } from "react";
import {
  StyleSheet,
  Text,
  View,
  FlatList,
  TouchableOpacity,
  Image,
  Dimensions,
} from "react-native";
import { Fontisto } from "@expo/vector-icons";
import ReactNativeHapticFeedback from "react-native-haptic-feedback";
import useImageSource from "@flexeee:common/utils/hooks/useImageSource";

import { Colors } from "@flexeee:common/theme/Colors";
import { Fonts } from "@flexeee:common/theme/Sizes";
import { Images } from "@flexeee:assets/images/Images";

const { width, height } = Dimensions.get("window");

const options = {
  enableVibrateFallback: true,
  ignoreAndroidSystemSettings: false,
};

export default function SubCategories({ navigation, workouts, category }) {
  
  const renderItem = ({ item }) => {
    const imageSrc = useImageSource(item.photo, Images.upperBody);
    return (
      <TouchableOpacity
        style={{ marginBottom: 10 * 2 }}
        onPress={() =>
          navigation.navigate("DetailStack", {
            screen: "WorkoutDetails",
            params: { item: item },
          }) & ReactNativeHapticFeedback.trigger("impactLight", options)
        }
      >
        {/* Image */}
        <View style={styles.workoutImageContainer}>
          {item.isLocked ? (
            <View style={{ backgroundColor: Colors.black, borderRadius: 10 }}>
              <Image
                source={imageSrc}
                resizeMode="cover"
                style={styles.workoutImage}
                opacity={0.75}
              />
            </View>
          ) : (
            <Image
              source={imageSrc}
              resizeMode="cover"
              style={styles.workoutImage}
            />
          )}
          <View style={styles.durationContainer}>
            <Text style={styles.title}>{item.duration}</Text>
          </View>
        </View>
        {item.isLocked && (
          <View style={styles.lockContainer}>
            <Fontisto name="locked" size={28} color={Colors.white} />
          </View>
        )}
        <View style={styles.subtitleContainer}>
          <Text style={styles.subtitle}>{item.name}</Text>
        </View>
      </TouchableOpacity>
    );
  };

  return (
    <View>
      <View style={styles.headingContainer}>
        <Text style={styles.heading}>{category.name}</Text>
        <TouchableOpacity
          onPress={() =>
            navigation.navigate("DetailStack", {
              screen: "WorkoutList",
              params: { category: category, workouts: workouts },
            }) & ReactNativeHapticFeedback.trigger("impactLight", options)
          }
        >
          <Text style={styles.viewOption}>View all</Text>
        </TouchableOpacity>
      </View>
      <FlatList
        data={workouts}
        horizontal
        keyExtractor={(item) => `${item.id}`}
        renderItem={renderItem}
        contentContainerStyle={{}}
        showsHorizontalScrollIndicator={false}
      />
    </View>
  );
}

DATA.js

这是我的数据的一些上下文(示例)

export const workoutData = [
  {
    id: 1,
    name: "Lower-body warm up",
    rating: 4.8,
    categories: [1],
    isLocked: false,
    description: `Ah, the infamous 'leg day.' Sometimes it's a struggle to even make it to the gym when you're planning to train your lower body, let alone spend time warming up before the often dreaded workout. But not only can avoiding a warm-up increase your risk of injury, it can also hinder your performance. This holds especially true when you walk into the gym after a night of sleep or a long day of sitting at a desk. A good warm-up will raise your body temperature, improve mobility and groove proper movement patterns. Some people require more mobility, while others require more stability. Regardless of your needs, there are several warm-up exercises that can prepare you for almost any type of lower-body exercise.\n \nTip: Spend five minutes on a foam roller before your warm-up to better prepare your muscles.`,
    photo: "lowerbody/deep-squat",
    duration: `5 mins`,
    trainer: {
      avatar: "lowerbody/deep-squat",
      name: "Amy",
    },
    workout: [
      {
        exerciseId: 1,
        name: "Forward Leg Swing (left)",
        photo: "lowerbody/forward-legswing",
        description:
          "Stand straight with your feet hip-width apart and hold onto a wall. Keeping one leg stationary, slowly swing the opposite leg forward and backward in a single smooth movement.",
        muscle: "Hip flexors, hamstrings, quadriceps, glutes & calves",
        duration: 30,
      },
      {
        exerciseId: 2,
        name: "Forward Leg Swing (right)",
        photo: "lowerbody/forward-legswing",
        description:
          "Stand straight with your feet hip-width apart and hold onto a wall. Keeping one leg stationary, slowly swing the opposite leg forward and backward in a single smooth movement.",
        muscle: "Hip flexors, hamstrings, quadriceps, glutes & calves",
        duration: 30,
      },

Firebase 存储文件结构

希望这些信息足以帮助我解决这个问题?如果不是,我很乐意提供更多详细信息 - 需要注意的是,在此之前,当我在我的 DATA.js 文件中本地调用我的文件时 正在工作 。只是需要一些想法或帮助来解释为什么这不起作用!

感谢您抽出宝贵时间,期待您的回复!

好吧,看来我的问题是我没有return渲染任何东西。我必须 return 另一个我称为 {company}Image 的组件,它 return 在渲染中编辑快速图像,称为 FastImage 并将图像作为道具。

希望这对阅读本文的人有用!