Magento 2 Experten — Hyvä Theme, Tailwind CSS & SEO aus einer Hand ›

Correctly Displaying Product Images and Stock

Correctly Displaying Product Images and Stock

~14 Min. Lesezeit Zuletzt aktualisiert am August 8, 2026

Two practically important data points are still missing: a real product image and current stock – the same API fields as the React web tutorial, displayed here with React Native's <Image> component.

Assembling the full image URL

api/magentoApi.js
// ... previous code ...

const MEDIA_BASE_URL = process.env.EXPO_PUBLIC_MAGENTO_MEDIA_URL;

export function getProductImage(product) {
  const mainImage = product.media_gallery_entries?.find((entry) =>
    entry.types?.includes('image')
  );
  const anyImage = product.media_gallery_entries?.[0];
  const entry = mainImage ?? anyImage;

  if (!entry) {
    return null;
  }

  return `${MEDIA_BASE_URL}/catalog/product${entry.file}`;
}

export function getStockInfo(product) {
  const stockItem = product.extension_attributes?.stock_item;
  return {
    inStock: stockItem?.is_in_stock ?? false,
    quantity: stockItem?.qty ?? 0,
  };
}

These two functions are – just like readCustomAttribute() in chapter 10 – practically IDENTICAL to the React web tutorial. The only difference: MEDIA_BASE_URL here comes from process.env.EXPO_PUBLIC_... instead of import.meta.env.VITE_....

ProductDetailScreen.js: integrating image and stock

screens/ProductDetailScreen.js
import { useEffect, useState } from 'react';
import { ScrollView, Text, Image, ActivityIndicator, StyleSheet } from 'react-native';
import {
  fetchProductBySku,
  readCustomAttribute,
  getProductImage,
  getStockInfo,
} from '../api/magentoApi';

export default function ProductDetailScreen({ route }) {
  const { sku } = route.params;
  const [product, setProduct] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    setLoading(true);
    async function load() {
      const data = await fetchProductBySku(sku);
      setProduct(data);
      setLoading(false);
    }
    load();
  }, [sku]);

  if (loading) {
    return <ActivityIndicator style={styles.centered} size="large" />;
  }

  const description = readCustomAttribute(product, 'description');
  const imageUrl = getProductImage(product);
  const { inStock, quantity } = getStockInfo(product);

  return (
    <ScrollView style={styles.container}>
      {imageUrl && (
        <Image source={{ uri: imageUrl }} style={styles.image} resizeMode="contain" />
      )}
      <Text style={styles.title}>{product.name}</Text>
      <Text>SKU: {product.sku}</Text>
      <Text>{product.price} €</Text>
      <Text>
        {inStock ? `In stock (${quantity} available)` : 'Out of stock'}
      </Text>
      {description && <Text style={styles.description}>{description}</Text>}
    </ScrollView>
  );
}

const styles = StyleSheet.create({
  centered: { flex: 1, justifyContent: 'center' },
  container: { padding: 16 },
  image: { width: '100%', height: 250, marginBottom: 16 },
  title: { fontSize: 20, fontWeight: 'bold', marginBottom: 8 },
  description: { marginTop: 16 },
});

Achtung: React Native's <Image> REQUIRES an explicit width/height in style (unlike HTML <img>, which uses the natural image size without one) – without these, the image won't render at all, or renders at size 0.

Tipp: The detail screen now REALLY shows all essential product data: image, name, SKU, price, stock, and description – test this with several of your real products, ideally on a real device via Expo Go, to check how images actually load over a mobile connection.