-
Notifications
You must be signed in to change notification settings - Fork 324
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Product provider work #1397
Product provider work #1397
Changes from 17 commits
4d44c01
d48eccc
722f704
dd2694c
1642902
0593cf3
49b01f7
6a032f6
a283cfb
0fe0e74
6f5d0b0
1b0a0a9
834be7b
cdc82ee
f4c0a41
7836e9b
8e2a262
80a757b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
--- | ||
'@shopify/hydrogen': minor | ||
--- | ||
|
||
## `<ProductProvider/>` and `<ProductOptionsProvider/>` | ||
|
||
- `<ProductProvider/>` has been removed | ||
- `<ProductPrice/>` was the only component left that used it; now it requires a `data` prop that takes in the product object | ||
- `<ProductOptionsProvider/>` now maintains and provides the state that `useProductOptions` used to keep track of by itself. This change enables you to use multiple `useProductOptions` hook calls and have them share the same state (such as selected variant, options, etc.) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,300 @@ | ||
--- | ||
gid: 80d51c7e-fafe-11eb-9a03-0242ac130003 | ||
title: ProductOptionsProvider | ||
description: The ProductOptionsProvider component sets up a context with state that tracks the selected variant and options. | ||
--- | ||
|
||
The `ProductOptionsProvider` component sets up a context with state that tracks the selected variant and options. Descendents of this component can use the [`useProductOptions`](https://shopify.dev/api/hydrogen/hooks/product-variant/useproductoptions) hook. | ||
|
||
## Example code | ||
|
||
```tsx | ||
import {ProductOptionsProvider, gql} from '@shopify/hydrogen'; | ||
|
||
const QUERY = gql` | ||
query product($handle: String!) { | ||
product: product(handle: $handle) { | ||
compareAtPriceRange { | ||
maxVariantPrice { | ||
currencyCode | ||
amount | ||
} | ||
minVariantPrice { | ||
currencyCode | ||
amount | ||
} | ||
} | ||
descriptionHtml | ||
handle | ||
id | ||
media(first: $numProductMedia) { | ||
nodes { | ||
... on MediaImage { | ||
mediaContentType | ||
image { | ||
id | ||
url | ||
altText | ||
width | ||
height | ||
} | ||
} | ||
... on Video { | ||
mediaContentType | ||
id | ||
previewImage { | ||
url | ||
} | ||
sources { | ||
mimeType | ||
url | ||
} | ||
} | ||
... on ExternalVideo { | ||
mediaContentType | ||
id | ||
embedUrl | ||
host | ||
} | ||
... on Model3d { | ||
mediaContentType | ||
id | ||
alt | ||
mediaContentType | ||
previewImage { | ||
url | ||
} | ||
sources { | ||
url | ||
} | ||
} | ||
} | ||
} | ||
metafields(first: $numProductMetafields) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Metafields as an array will need to be removed. Our API no longer supports this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yup that work is coming up. This was just a copy/paste from previous file. |
||
nodes { | ||
id | ||
type | ||
namespace | ||
key | ||
value | ||
createdAt | ||
updatedAt | ||
description | ||
reference @include(if: $includeReferenceMetafieldDetails) { | ||
__typename | ||
... on MediaImage { | ||
id | ||
mediaContentType | ||
image { | ||
id | ||
url | ||
altText | ||
width | ||
height | ||
} | ||
} | ||
} | ||
} | ||
} | ||
priceRange { | ||
maxVariantPrice { | ||
currencyCode | ||
amount | ||
} | ||
minVariantPrice { | ||
currencyCode | ||
amount | ||
} | ||
} | ||
title | ||
variants(first: $numProductVariants) { | ||
nodes { | ||
id | ||
title | ||
availableForSale | ||
image { | ||
id | ||
url | ||
altText | ||
width | ||
height | ||
} | ||
unitPriceMeasurement { | ||
measuredType | ||
quantityUnit | ||
quantityValue | ||
referenceUnit | ||
referenceValue | ||
} | ||
unitPrice { | ||
currencyCode | ||
amount | ||
} | ||
priceV2 { | ||
currencyCode | ||
amount | ||
} | ||
compareAtPriceV2 { | ||
currencyCode | ||
amount | ||
} | ||
selectedOptions { | ||
name | ||
value | ||
} | ||
metafields(first: $numProductVariantMetafields) { | ||
nodes { | ||
id | ||
type | ||
namespace | ||
key | ||
value | ||
createdAt | ||
updatedAt | ||
description | ||
reference @include(if: $includeReferenceMetafieldDetails) { | ||
__typename | ||
... on MediaImage { | ||
id | ||
mediaContentType | ||
image { | ||
id | ||
url | ||
altText | ||
width | ||
height | ||
} | ||
} | ||
} | ||
} | ||
} | ||
sellingPlanAllocations( | ||
first: $numProductVariantSellingPlanAllocations | ||
) { | ||
nodes { | ||
priceAdjustments { | ||
compareAtPrice { | ||
currencyCode | ||
amount | ||
} | ||
perDeliveryPrice { | ||
currencyCode | ||
amount | ||
} | ||
price { | ||
currencyCode | ||
amount | ||
} | ||
unitPrice { | ||
currencyCode | ||
amount | ||
} | ||
} | ||
sellingPlan { | ||
id | ||
description | ||
name | ||
options { | ||
name | ||
value | ||
} | ||
priceAdjustments { | ||
orderCount | ||
adjustmentValue { | ||
... on SellingPlanFixedAmountPriceAdjustment { | ||
adjustmentAmount { | ||
currencyCode | ||
amount | ||
} | ||
} | ||
... on SellingPlanFixedPriceAdjustment { | ||
price { | ||
currencyCode | ||
amount | ||
} | ||
} | ||
... on SellingPlanPercentagePriceAdjustment { | ||
adjustmentPercentage | ||
} | ||
} | ||
} | ||
recurringDeliveries | ||
} | ||
} | ||
} | ||
} | ||
} | ||
sellingPlanGroups(first: $numProductSellingPlanGroups) { | ||
nodes { | ||
sellingPlans(first: $numProductSellingPlans) { | ||
nodes { | ||
id | ||
description | ||
name | ||
options { | ||
name | ||
value | ||
} | ||
priceAdjustments { | ||
orderCount | ||
adjustmentValue { | ||
... on SellingPlanFixedAmountPriceAdjustment { | ||
adjustmentAmount { | ||
currencyCode | ||
amount | ||
} | ||
} | ||
... on SellingPlanFixedPriceAdjustment { | ||
price { | ||
currencyCode | ||
amount | ||
} | ||
} | ||
... on SellingPlanPercentagePriceAdjustment { | ||
adjustmentPercentage | ||
} | ||
} | ||
} | ||
recurringDeliveries | ||
} | ||
} | ||
appName | ||
name | ||
options { | ||
name | ||
values | ||
} | ||
} | ||
} | ||
} | ||
} | ||
`; | ||
|
||
export function Product() { | ||
const {data} = useShopQuery({query: QUERY}); | ||
|
||
return ( | ||
<ProductOptionsProvider data={data.product} initialVariantId="some-id">{/* Your JSX */}</ProductOptionsProvider> | ||
); | ||
} | ||
``` | ||
|
||
## Props | ||
|
||
| Name | Type | Description | | ||
| ----------------- | --------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ||
| children | <code>ReactNode</code> | A `ReactNode` element. | | ||
| data | <code>PartialDeep<ProductType></code> | An object with fields that correspond to the Storefront API's [Product object](/api/storefront/reference/products/product). | | ||
| initialVariantId? | <code>Parameters<typeof useProductOption>['0']['initialvariantid']</code> | The initially selected variant. <br></br>The following logic applies to `initialVariantId`:<ul><li>If `initialVariantId` is provided, then it's used, even if it's out of stock.</li><li>If `initialVariantId` is provided, but is `null`, then no variant is used.</li><li>If nothing is passed to `initialVariantId`, and you're in a `ProductOptionsProvider` component, then `selectedVariant.id` is used.</li><li>If nothing is passed to `initialVariantId` and you're not in a `ProductOptionsProvider` component, then the first available or in-stock variant is used.</li><li>If nothing is passed to `initialVariantId`, you're not in a `ProductOptionsProvider` component, and no variants are in stock, then the first variant is used.</li></ul> | | ||
|
||
## Component type | ||
|
||
The `ProductOptionsProvider` component is a client component, which means that it renders on the client. For more information about component types, refer to [React Server Components](https://shopify.dev/custom-storefronts/hydrogen/framework/react-server-components). | ||
|
||
## Related components | ||
|
||
- [`ProductPrice`](https://shopify.dev/api/hydrogen/components/product-variant/productprice) | ||
|
||
## Related hooks | ||
|
||
- [`useProductOptions`](https://shopify.dev/api/hydrogen/hooks/product-variant/useproductoptions) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This query can be improved via …
Sadly the id can't actually be pulled up to the top.