Have your say in Community Polls: What was/is your greatest motivation to start your own business?

Customer Metafield in Checkout UI Extension Not Readable

Solved

Customer Metafield in Checkout UI Extension Not Readable

mlightner
Shopify Partner
2 1 1

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:

mlightner_0-1711721487489.png

 

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

 

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:

mlightner_1-1711721836140.png

 

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', () => (
  <Extension />
));

 

LocationDisplay.jsx

 

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 (
    <Text>TEST</Text> 
);
}

 

 

Accepted Solution (1)
mlightner
Shopify Partner
2 1 1

This is an accepted solution.

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.

View solution in original post

Replies 2 (2)

zaidkhan
Shopify Partner
15 0 1

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?

mlightner
Shopify Partner
2 1 1

This is an accepted solution.

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.