Im creating a post purchase extension,
I manage to render the extension, and make the request to my server to conditionaly render it
but when i try to use any react hook inside the App function i get the error :
"Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
- You might have mismatching versions of React and the renderer (such as React DOM)
- You might be breaking the Rules of Hooks
- You might have more than one copy of React in the same app"
here is my code :
/**
* Extend Shopify Checkout with a custom Post Purchase user experience.
* This template provides two extension points:
*
* 1. ShouldRender - Called first, during the checkout process, when the
* payment page loads.
* 2. Render - If requested by `ShouldRender`, will be rendered after checkout
* completes
*/
import React, { useEffect, useState } from 'react';
import {
extend,
render,
BlockStack,
Button,
CalloutBanner,
Heading,
Image,
Layout,
TextBlock,
TextContainer,
View,
useExtensionInput,
} from '@shopify/post-purchase-ui-extensions-react';
/**
* Entry point for the `ShouldRender` Extension Point.
*
* Returns a value indicating whether or not to render a PostPurchase step, and
* optionally allows data to be stored on the client for use in the `Render`
* extension point.
*/
const APP_URL = 'myappurl.com';
extend('Checkout::PostPurchase::ShouldRender', async ({ inputData, storage }) => {
try {
const postPurchaseOffer = await fetch(`${APP_URL}/api/proxy/post-purchase`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${inputData.token}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
referenceId: inputData.initialPurchase.referenceId,
}),
});
const fetchResult = await postPurchaseOffer.json();
console.log(fetchResult.render, 'fetchResult.render');
await storage.update(fetchResult);
// For local development, always show the post-purchase page
return { render: fetchResult.render };
} catch (error) {
console.log('Error fetching post-purchase offer:', error);
return { render: true };
}
});
/**
* Entry point for the `Render` Extension Point
*
* Returns markup composed of remote UI components. The Render extension can
* optionally make use of data stored during `ShouldRender` extension point to
* expedite time-to-first-meaningful-paint.
*/
// Top-level React component
export const App = () => {
// const { storage, inputData, calculateChangeset, applyChangeset, done } = useExtensionInput();
const [loading, setLoading] = useState(true);
// const [calculatedPurchase, setCalculatedPurchase] = useState();
// const { offers } = storage.initialData;
return (
<BlockStack spacing="loose">
<CalloutBanner title="Post-purchase extension template">
Use this template as a starting point to build a great post-purchase extension.
</CalloutBanner>
<Layout
maxInlineSize={0.95}
media={[
{ viewportSize: 'small', sizes: [1, 30, 1] },
{ viewportSize: 'medium', sizes: [300, 30, 0.5] },
{ viewportSize: 'large', sizes: [400, 30, 0.33] },
]}
>
<View>
<Image source="https://cdn.shopify.com/static/images/examples/img-placeholder-1120x1120.png" />
</View>
<View />
<BlockStack spacing="xloose">
<TextContainer>
<Heading>Post-purchase extension</Heading>
<TextBlock>Here you can cross-sell other products, request a product review based on a previous purchase, and much more.</TextBlock>
</TextContainer>
<Button
submit
onPress={() => {
// eslint-disable-next-line no-console
// console.log(`Extension point ${extensionPoint}`, initialState);
console.log('asd');
}}
>
Primary button
</Button>
</BlockStack>
</Layout>
</BlockStack>
);
};
render('Checkout::PostPurchase::Render', App);
here is my extension package.json :
{
"name": "post-purchase-ui",
"private": true,
"version": "1.0.0",
"main": "dist/main.js",
"license": "UNLICENSED",
"dependencies": {
"@shopify/post-purchase-ui-extensions-react": "^0.13.2",
"jsonwebtoken": "^9.0.2",
"react": "^18.2.0",
"uuid": "^9.0.1"
},
"devDependencies": {
"@types/react": "^18.2.38"
}
}
Please help ![]()