Showing Metafields on a Product Display Card
A Product List Item Display Card that shows two custom metafields (vendor and concentration_category) alongside the title and price, with a skeleton placeholder while the product is still loading.
Example
import React from 'react';
import { Actionable, Box, Flexbox, Image, Text, Button } from '@evlop/native-components';
import { Money, loadProductsManager, CustomBlock } from '@evlop/shopify';
loadProductsManager.addMetafieldIdentifiers([
{ namespace: 'custom', key: 'concentration_category' },
{ namespace: 'custom', key: 'vendor' },
]);
const skeleton = <Box borderRadius={5} bg="gray-100" style={{ aspectRatio: 1 }} />;
const ProductDisplayCard: CustomBlock.ProductListItem = ({ data }) => {
const { product } = data;
if (product?.isLoading) return skeleton;
return (
<Actionable action={product.actions.openDetailsPage}>
<Flexbox flexDirection="column" gap={10}>
<Flexbox flexDirection="column" gap={5}>
<Image
borderRadius={5}
resizeMode="cover"
src={product.images[0].url}
aspectRatio={1}
/>
</Flexbox>
<Flexbox flexDirection="column" gap={4} alignItems="center">
<Text fontSize="xs" textAlign="center">{product.metafields?.custom?.vendor}</Text>
<Text textAlign="center" numberOfLines={2} fontSize="sm" fontWeight="Bold">{product.title}</Text>
<Text fontSize="xs" textAlign="center">{product.metafields?.custom?.concentration_category}</Text>
<Money fontWeight="Bold" price={product.variants[0].price} />
</Flexbox>
</Flexbox>
</Actionable>
);
};
export default ProductDisplayCard;
How it works
- Register the metafields once, at module scope.
loadProductsManager.addMetafieldIdentifiers([{ namespace, key }, ...])is called alongside the imports, outside the component function - never inside the render body. This tells the product loader which metafields to fetch for every product it loads. - Read them off
product.metafields. A registered{ namespace: 'custom', key: 'vendor' }identifier lands atproduct.metafields.custom.vendor. Access it with optional chaining (product.metafields?.custom?.vendor) since a metafield may be unset on a given product. - Guard the loading state first.
product?.isLoadingis checked before touchingimages/variants/metafields, returning askeleton- a gray<Box>matching the card's own image dimensions - rather than rendering with data that isn't there yet. - Type the component.
CustomBlock.ProductListItem(from@evlop/shopify) typesdata.productas a fullShopifyProduct, including the registered metafields, without needing to declare your own props interface.
See Product List Item Display Card for the rest of that block type's data shape, and Available Packages for what else @evlop/shopify exports.