Customer Metafield in Checkout UI Extension Not Readable

I am trying to get the value for a Customer metafield in a checkout UI extension. With this code:

const storeNameMetafield = useAppMetafields({
        type: "customer",
        namespace: "locator",
        key: "store_name"
    });
    console.log("storeNameMetafield", storeNameMetafield);
    const storeName = storeNameMetafield[0];
    console.log("storeName", storeName);

I can see the metafield data being logged as an object:

However, if I change that code to get the metafield value (const storeName = storeNameMetafield[0~~]~~ to storeNameMetafield[0]**.**metafield.value :disappointed_face:

const storeNameMetafield = useAppMetafields({
        type: "customer",
        namespace: "locator",
        key: "store_name"
    });
    console.log("storeNameMetafield", storeNameMetafield);
    const storeName = storeNameMetafield[0].metafield.value;
    console.log("storeName", storeName);

the metafield array is empty and I get the following error:

Any thoughts on why this is happening?

Full code, in case it’s relevant:

shopify.extension.toml

# Learn more about configuring your checkout UI extension:
# https://shopify.dev/api/checkout-extensions/checkout/configuration

# The version of APIs your extension will receive. Learn more:
# https://shopify.dev/docs/api/usage/versioning
api_version = "2024-01"

[[extensions]]
type = "ui_extension"
name = "checkout-ui"
handle = "checkout-ui"

# Controls where in Shopify your extension will be injected,
# and the file that contains your extension’s source code. Learn more:
# https://shopify.dev/docs/api/checkout-ui-extensions/unstable/extension-targets-overview

[[extensions.targeting]]
module = "./src/Checkout.jsx"
target = "purchase.checkout.header.render-after"
    [[extensions.targeting.metafields]]
    namespace = "locator"
    key = "store_name"

[extensions.capabilities]
# Gives your extension access to directly query Shopify’s storefront API.
# https://shopify.dev/docs/api/checkout-ui-extensions/unstable/configuration#api-access
api_access = true

# Gives your extension access to make external network calls, using the
# JavaScript `fetch()` API. Learn more:
# https://shopify.dev/docs/api/checkout-ui-extensions/unstable/configuration#network-access
network_access = true

# Loads metafields on checkout resources, including the cart,
# products, customers, and more. Learn more:
# https://shopify.dev/docs/api/checkout-ui-extensions/unstable/configuration#metafields

# Defines settings that will be collected from merchants installing
# your extension. Learn more:
# https://shopify.dev/docs/api/checkout-ui-extensions/unstable/configuration#settings-definition

# [extensions.settings]
# [[extensions.settings.fields]]
# key = "banner_title"
# type = "single_line_text_field"
# name = "Banner title"
# description = "Enter a title for the banner"

Checkout.jsx

import {reactExtension} from '@shopify/ui-extensions-react/checkout';

import Extension from './LocationDisplay.jsx';

export default reactExtension('purchase.checkout.header.render-after', () => (
  

LocationDisplay.jsx

```javascript
import {
  Text,
  useAppMetafields,
} from "@shopify/ui-extensions-react/checkout";

export default function Extension() {
    //get customer storename metafield
    const storeNameMetafield = useAppMetafields({
        type: "customer",
        namespace: "locator",
        key: "store_name"
    });
    console.log("storeNameMetafield", storeNameMetafield);
    const storeName = storeNameMetafield[0].metafield.value;
    console.log("storeName", storeName);

  return (
    TEST 
);
}

Hi, Did you ever get a solution. I have the exact same problem and if you can help out please.
I am guessing the issue is with scopes, what scopes are needed to resolve this?

The solution to my issue was actually very simple. Completely due to me inexperience with React.

As far as I understand, when the page first renders, storeNameMetafield may not be immediately populated. So when we try to assign storeName, storeNameMetafield[0] is undefined, which causes an error that halts the code.

The easy solution was to change

const storeName = storeNameMetafield[0].metafield.value;

to

const storeName = storeNameMetafield[0]?.metafield.value;

so that when there is no value yet, we avoid error. On the next render, the value is there to read and will display as expected.

const storeNameMetafield = useAppMetafields({
    type: "customer",
    namespace: "locator",
    key: "store_name"
});
console.log("storeNameMetafield", storeNameMetafield);
const storeName = storeNameMetafield[0]?.metafield.value;
console.log("storeName", storeName);

To answer your question, my app has the following scopes:

“read_customers, read_orders, write_customers, write_orders”

though I believe all that’s required for this is read_customers.

2 Likes

Thank you for posting your solution. I was stuck on this for hours!