I am building a series of shopify checkout UI extensions, because they have pulled the rug out from under us Shopify Plus customers and removed the ability to modify our checkout.liquid files. The system I am building is a rewards/points keeping system that tracks and rewards people for purchasing certain items.
[[extensions.targeting]]
module = "./src/Banner.tsx"
target = "purchase.checkout.block.render"
[[extensions.targeting]]
module = "./src/LineItems.tsx"
target = "purchase.checkout.cart-line-item.render-after"
[[extensions.targeting]]
module = "./src/Calculator.tsx"
target = "purchase.checkout.reductions.render-after"
All I want to do is share a single integer between all 3 components. This integer is just a multiplier for a points keeping/rewards system. I am new to react and have recently learned of useContext. But I’m not sure how to share it between 3 .tsx files.
Really all my components kind of look like this below and I just want that one variable to be shared between all 3 of these components so that I can update it in one place. We frequently change these multipliers based on promotions so having it in a single spot is ideal.
import { useEffect, useState, useRef } from 'react';
import {
Heading,
useApi,
InlineLayout,
Text,
View,
useApplyDiscountCodeChange,
useDiscountCodes,
useAppMetafields,
reactExtension,
} from '@shopify/ui-extensions-react/checkout';
export default reactExtension(
'purchase.checkout.reductions.render-after',
() => <Extension />,
);
function Extension() {
const { extension, lines } = useApi();
const productMetaDatas = useAppMetafields({
type: "product",
namespace: "custom",
key: "entry_override_arbitrary_value"
});
let multiplier = 40;
let [messageHeader, setMessageHeader] = useState('Total Entries');
let [message, setMessage] = useState('You will receive 40 entries for every $1 spent!');
const discountCodes = useDiscountCodes();
const ApplyDiscountCodeChange = useApplyDiscountCodeChange();
useEffect(() => {
let tempEntries = 0;
lines.current.forEach(function (cartLineTarget) {
// Get the product ID from the cart line item
const productId = cartLineTarget?.merchandise?.product?.id;
if (!productId) {
return;
}
const productMetaData = productMetaDatas.find(({ target }) => {
return `gid://shopify/Product/${target.id}` === productId;
});
if (productMetaData?.metafield.value) {
tempEntries += parseInt(productMetaData.metafield.value) * cartLineTarget.quantity;
} else {
tempEntries += Math.floor(cartLineTarget.cost.totalAmount.amount) * cartLineTarget.quantity * multiplier;
}
});
const bonusDiscountCodes = [
{ 'FREESHIPPING2024': 50 },
{ 'CLOWNSHOES': 20 },
];
if (discountCodes.length > 0) {
const isActiveDiscountCodeInBonus = bonusDiscountCodes.some(discountCodeObj =>
Object.keys(discountCodeObj).includes(discountCodes[0].code)
);
if (isActiveDiscountCodeInBonus) {
tempEntries += 50;
}
}
setMessage(tempEntries);
}, [message, messageHeader, lines, productMetaDatas, discountCodes]);
return (
<InlineLayout columns={['fill', '20%']}>
<View>
<Heading level="2">{messageHeader}</Heading>
</View>
<View inlineAlignment="end">
<Text appearance="info">{message}</Text>
</View>
</InlineLayout>
);
}
Right now I’ve just duplicated the declared “multiplier” variable between all 3 components. But that’s not an ideal situation. I know there is a simple solution but I cant for the life of me figure it out.
Nick Koskowski is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.