fix(dashboard): avoid unnecessary product relations to be returned by default (#14175)
## Summary
**What** — What changes are introduced in this PR?
Improve Admin UI product detail performance after updating the entity.
**Why** — Why are these changes relevant or necessary?
Products with a lot of relations would cause issues when trying to be updated through various edit components, since the core update api route returns these entities by default.
**How** — How have these changes been implemented?
We remove these unnecessary relations when calling the update route, by passing the `fields` query param with the negation sign for each of these. For example: `fields=-type,-collection...`
**Testing** — How have these changes been tested, or how can the reviewer test the feature?
Tested all of the update components and validated they still work correctly, plus, none depend on the returned product to perform an action or render information.
---
## Examples
Provide examples or code snippets that demonstrate how this feature works, or how it can be used in practice.
This helps with documentation and ensures maintainers can quickly understand and verify the change.
```ts
// Example usage
```
---
## Checklist
Please ensure the following before requesting a review:
- [x] I have added a **changeset** for this PR
- Every non-breaking change should be marked as a **patch**
- To add a changeset, run `yarn changeset` and follow the prompts
- [ ] The changes are covered by relevant **tests**
- [x] I have verified the code works as intended locally
- [x] I have linked the related issue(s) if applicable
---
## Additional Context
Add any additional context, related issues, or references that might help the reviewer understand this PR.
fixes #13783, #14183
closes CORE-1296, SUP-2791
Co-authored-by: Adrien de Peretti <25098370+adrien2p@users.noreply.github.com>
This commit is contained in:
@@ -117,7 +117,9 @@ const useDynamicSearchResults = (
|
||||
{
|
||||
q: debouncedSearch,
|
||||
limit,
|
||||
fields: "id,title,thumbnail",
|
||||
// TODO: Remove exclusion once we avoid including unnecessary relations by default in the query config
|
||||
fields:
|
||||
"id,title,thumbnail,-type,-collection,-options,-tags,-images,-variants,-sales_channels",
|
||||
},
|
||||
{
|
||||
enabled: isAreaEnabled(currentArea, "product"),
|
||||
|
||||
@@ -340,7 +340,11 @@ export const useUpdateProduct = (
|
||||
>
|
||||
) => {
|
||||
return useMutation({
|
||||
mutationFn: (payload) => sdk.admin.product.update(id, payload),
|
||||
mutationFn: (payload) =>
|
||||
sdk.admin.product.update(id, payload, {
|
||||
fields:
|
||||
"-type,-collection,-options,-tags,-images,-variants,-sales_channels",
|
||||
}),
|
||||
onSuccess: async (data, variables, context) => {
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey: productsQueryKeys.lists(),
|
||||
|
||||
@@ -7,7 +7,8 @@ type UseProductTableQueryProps = {
|
||||
}
|
||||
|
||||
const DEFAULT_FIELDS =
|
||||
"id,title,handle,status,*collection,*sales_channels,variants.id,thumbnail"
|
||||
// TODO: Remove exclusion once we avoid including unnecessary relations by default in the query config
|
||||
"id,title,handle,status,*collection,*sales_channels,variants.id,thumbnail,-type,-options,-tags,-images,-variants"
|
||||
|
||||
export const useProductTableQuery = ({
|
||||
prefix,
|
||||
|
||||
@@ -35,7 +35,9 @@ export const PriceListPricesForm = ({
|
||||
const { products, isLoading, isError, error } = useProducts({
|
||||
id: ids.map((id) => id.id),
|
||||
limit: ids.length,
|
||||
fields: "title,thumbnail,*variants",
|
||||
// TODO: Remove exclusion once we avoid including unnecessary relations by default in the query config
|
||||
fields:
|
||||
"title,thumbnail,*variants,-type,-collection,-options,-tags,-images,-sales_channels",
|
||||
})
|
||||
|
||||
const { setCloseOnEscape } = useRouteModal()
|
||||
|
||||
@@ -36,7 +36,9 @@ export const PriceListPricesAddPricesForm = ({
|
||||
const { products, isLoading, isError, error } = useProducts({
|
||||
id: ids.map((id) => id.id),
|
||||
limit: ids.length,
|
||||
fields: "title,thumbnail,*variants",
|
||||
// TODO: Remove exclusion once we avoid including unnecessary relations by default in the query config
|
||||
fields:
|
||||
"title,thumbnail,*variants,-type,-collection,-options,-tags,-images,-sales_channels",
|
||||
})
|
||||
|
||||
const { setValue } = form
|
||||
|
||||
@@ -22,7 +22,9 @@ export const PriceListPricesEdit = () => {
|
||||
id: productIds,
|
||||
limit: productIds?.length || 9999, // Temporary until we support lazy loading in the DataGrid
|
||||
price_list_id: [id!],
|
||||
fields: "title,thumbnail,*variants",
|
||||
// TODO: Remove exclusion once we avoid including unnecessary relations by default in the query config
|
||||
fields:
|
||||
"title,thumbnail,*variants,-type,-collection,-options,-tags,-images,-sales_channels",
|
||||
})
|
||||
|
||||
const { isReady, regions, currencies, pricePreferences } =
|
||||
|
||||
@@ -33,7 +33,8 @@ export const ProductVariantEdit = () => {
|
||||
} = useProduct(
|
||||
variant?.product_id!,
|
||||
{
|
||||
fields: "-variants",
|
||||
// TODO: Remove exclusion once we avoid including unnecessary relations by default in the query config
|
||||
fields: "-type,-collection,-tags,-images,-variants,-sales_channels",
|
||||
},
|
||||
{
|
||||
enabled: !!variant?.product_id,
|
||||
|
||||
@@ -4,7 +4,6 @@ import { useParams } from "react-router-dom"
|
||||
|
||||
import { RouteDrawer } from "../../../components/modals"
|
||||
import { useProduct } from "../../../hooks/api/products"
|
||||
import { PRODUCT_DETAIL_FIELDS } from "../product-detail/constants"
|
||||
import { ProductAttributesForm } from "./components/product-attributes-form"
|
||||
|
||||
export const ProductAttributes = () => {
|
||||
@@ -12,7 +11,9 @@ export const ProductAttributes = () => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
const { product, isLoading, isError, error } = useProduct(id!, {
|
||||
fields: PRODUCT_DETAIL_FIELDS,
|
||||
// TODO: Remove exclusion once we avoid including unnecessary relations by default in the query config
|
||||
fields:
|
||||
"-type,-collection,-options,-tags,-images,-variants,-sales_channels",
|
||||
})
|
||||
|
||||
if (isError) {
|
||||
|
||||
@@ -9,7 +9,11 @@ export const ProductCreateOption = () => {
|
||||
const { id } = useParams()
|
||||
const { t } = useTranslation()
|
||||
|
||||
const { product, isLoading, isError, error } = useProduct(id!)
|
||||
const { product, isLoading, isError, error } = useProduct(id!, {
|
||||
// TODO: Remove exclusion once we avoid including unnecessary relations by default in the query config
|
||||
fields:
|
||||
"-type,-collection,-options,-tags,-images,-variants,-sales_channels",
|
||||
})
|
||||
|
||||
if (isError) {
|
||||
throw error
|
||||
|
||||
@@ -6,7 +6,10 @@ import { CreateProductVariantForm } from "./components/create-product-variant-fo
|
||||
export const ProductCreateVariant = () => {
|
||||
const { id } = useParams()
|
||||
|
||||
const { product, isLoading, isError, error } = useProduct(id!)
|
||||
const { product, isLoading, isError, error } = useProduct(id!, {
|
||||
// TODO: Remove exclusion once we avoid including unnecessary relations by default in the query config
|
||||
fields: "-type,-collection,-tags,-images,-variants,-sales_channels",
|
||||
})
|
||||
|
||||
if (isError) {
|
||||
throw error
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { HttpTypes } from "@medusajs/types"
|
||||
import { UIMatch } from "react-router-dom"
|
||||
import { useProduct } from "../../../hooks/api"
|
||||
import { PRODUCT_DETAIL_FIELDS } from "./constants"
|
||||
|
||||
type ProductDetailBreadcrumbProps = UIMatch<HttpTypes.AdminProductResponse>
|
||||
|
||||
@@ -13,7 +12,9 @@ export const ProductDetailBreadcrumb = (
|
||||
const { product } = useProduct(
|
||||
id!,
|
||||
{
|
||||
fields: PRODUCT_DETAIL_FIELDS,
|
||||
// TODO: Remove exclusion once we avoid including unnecessary relations by default in the query config
|
||||
fields:
|
||||
"-type,-collection,-options,-tags,-images,-variants,-sales_channels",
|
||||
},
|
||||
{
|
||||
initialData: props.data,
|
||||
|
||||
@@ -9,7 +9,10 @@ export const ProductEditOption = () => {
|
||||
const { id, option_id } = useParams()
|
||||
const { t } = useTranslation()
|
||||
|
||||
const { product, isPending, isFetching, isError, error } = useProduct(id!)
|
||||
const { product, isPending, isFetching, isError, error } = useProduct(id!, {
|
||||
// TODO: Remove exclusion once we avoid including unnecessary relations by default in the query config
|
||||
fields: "-type,-collection,-tags,-images,-variants,-sales_channels",
|
||||
})
|
||||
|
||||
const option = product?.options.find((o) => o.id === option_id)
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ import { useParams } from "react-router-dom"
|
||||
|
||||
import { RouteDrawer } from "../../../components/modals"
|
||||
import { useProduct } from "../../../hooks/api/products"
|
||||
import { PRODUCT_DETAIL_FIELDS } from "../product-detail/constants"
|
||||
import { EditProductForm } from "./components/edit-product-form"
|
||||
|
||||
export const ProductEdit = () => {
|
||||
@@ -12,7 +11,9 @@ export const ProductEdit = () => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
const { product, isLoading, isError, error } = useProduct(id!, {
|
||||
fields: PRODUCT_DETAIL_FIELDS,
|
||||
// TODO: Remove exclusion once we avoid including unnecessary relations by default in the query config
|
||||
fields:
|
||||
"-type,-collection,-options,-tags,-images,-variants,-sales_channels",
|
||||
})
|
||||
|
||||
if (isError) {
|
||||
|
||||
@@ -21,7 +21,11 @@ export const ProductImageVariantsEdit = () => {
|
||||
|
||||
const { product, isPending } = useProduct(
|
||||
product_id!,
|
||||
{ fields: "images.id,images.url,images.variants.id" },
|
||||
{
|
||||
// TODO: Remove exclusion once we avoid including unnecessary relations by default in the query config
|
||||
fields:
|
||||
"images.id,images.url,images.variants.id,-type,-collection,-options,-tags,-variants,-sales_channels",
|
||||
},
|
||||
{
|
||||
enabled: !!product_id && !!image_id,
|
||||
}
|
||||
|
||||
@@ -8,7 +8,10 @@ export const ProductMedia = () => {
|
||||
const { t } = useTranslation()
|
||||
const { id } = useParams()
|
||||
|
||||
const { product, isLoading, isError, error } = useProduct(id!)
|
||||
const { product, isLoading, isError, error } = useProduct(id!, {
|
||||
// TODO: Remove exclusion once we avoid including unnecessary relations by default in the query config
|
||||
fields: "-type,-collection,-options,-tags,-variants,-sales_channels",
|
||||
})
|
||||
|
||||
const ready = !isLoading && product
|
||||
|
||||
|
||||
@@ -5,7 +5,11 @@ import { useProduct, useUpdateProduct } from "../../../hooks/api"
|
||||
export const ProductMetadata = () => {
|
||||
const { id } = useParams()
|
||||
|
||||
const { product, isPending, isError, error } = useProduct(id!)
|
||||
const { product, isPending, isError, error } = useProduct(id!, {
|
||||
// TODO: Remove exclusion once we avoid including unnecessary relations by default in the query config
|
||||
fields:
|
||||
"-type,-collection,-options,-tags,-images,-variants,-sales_channels",
|
||||
})
|
||||
|
||||
const { mutateAsync, isPending: isMutating } = useUpdateProduct(product?.id!)
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ import { useParams } from "react-router-dom"
|
||||
|
||||
import { RouteDrawer } from "../../../components/modals"
|
||||
import { useProduct } from "../../../hooks/api/products"
|
||||
import { PRODUCT_DETAIL_FIELDS } from "../product-detail/constants"
|
||||
import { ProductOrganizationForm } from "./components/product-organization-form"
|
||||
|
||||
export const ProductOrganization = () => {
|
||||
@@ -12,7 +11,8 @@ export const ProductOrganization = () => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
const { product, isLoading, isError, error } = useProduct(id!, {
|
||||
fields: PRODUCT_DETAIL_FIELDS,
|
||||
// TODO: Remove exclusion once we avoid including unnecessary relations by default in the query config
|
||||
fields: "*categories,-options,-images,-variants,-sales_channels",
|
||||
})
|
||||
|
||||
if (isError) {
|
||||
|
||||
@@ -7,7 +7,10 @@ import { PricingEdit } from "./pricing-edit"
|
||||
export const ProductPrices = () => {
|
||||
const { id, variant_id } = useParams()
|
||||
|
||||
const { product, isLoading, isError, error } = useProduct(id!)
|
||||
const { product, isLoading, isError, error } = useProduct(id!, {
|
||||
// TODO: Remove exclusion once we avoid including unnecessary relations by default in the query config
|
||||
fields: "-type,-collection,-options,-tags,-images,-sales_channels",
|
||||
})
|
||||
|
||||
if (isError) {
|
||||
throw error
|
||||
|
||||
@@ -6,7 +6,10 @@ import { EditSalesChannelsForm } from "./components/edit-sales-channels-form"
|
||||
|
||||
export const ProductSalesChannels = () => {
|
||||
const { id } = useParams()
|
||||
const { product, isLoading, isError, error } = useProduct(id!)
|
||||
const { product, isLoading, isError, error } = useProduct(id!, {
|
||||
// TODO: Remove exclusion once we avoid including unnecessary relations by default in the query config
|
||||
fields: "-type,-collection,-options,-tags,-images,-variants",
|
||||
})
|
||||
|
||||
if (isError) {
|
||||
throw error
|
||||
|
||||
@@ -4,7 +4,6 @@ import { useParams } from "react-router-dom"
|
||||
|
||||
import { RouteDrawer } from "../../../components/modals"
|
||||
import { useProduct } from "../../../hooks/api/products"
|
||||
import { PRODUCT_DETAIL_FIELDS } from "../product-detail/constants"
|
||||
import { ProductShippingProfileForm } from "./components/product-organization-form"
|
||||
|
||||
export const ProductShippingProfile = () => {
|
||||
@@ -12,7 +11,9 @@ export const ProductShippingProfile = () => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
const { product, isLoading, isError, error } = useProduct(id!, {
|
||||
fields: PRODUCT_DETAIL_FIELDS,
|
||||
// TODO: Remove exclusion once we avoid including unnecessary relations by default in the query config
|
||||
fields:
|
||||
"*shipping_profile,-type,-collection,-options,-tags,-images,-variants,-sales_channels",
|
||||
})
|
||||
|
||||
if (isError) {
|
||||
|
||||
@@ -17,7 +17,11 @@ export const TargetItem = ({
|
||||
}: TargetItemProps) => {
|
||||
const { product } = useProduct(
|
||||
value,
|
||||
{ fields: "id,title" },
|
||||
{
|
||||
// TODO: Remove exclusion once we avoid including unnecessary relations by default in the query config
|
||||
fields:
|
||||
"id,title,-type,-collection,-options,-tags,-images,-variants,-sales_channels",
|
||||
},
|
||||
{ enabled: !label }
|
||||
)
|
||||
|
||||
|
||||
@@ -39,18 +39,15 @@ export const TaxOverrideCard = ({ taxRate }: TaxOverrideCardProps) => {
|
||||
return null
|
||||
}
|
||||
|
||||
const groupedRules = taxRate.rules.reduce(
|
||||
(acc, rule) => {
|
||||
if (!acc[rule.reference]) {
|
||||
acc[rule.reference] = []
|
||||
}
|
||||
const groupedRules = taxRate.rules.reduce((acc, rule) => {
|
||||
if (!acc[rule.reference]) {
|
||||
acc[rule.reference] = []
|
||||
}
|
||||
|
||||
acc[rule.reference].push(rule.reference_id)
|
||||
acc[rule.reference].push(rule.reference_id)
|
||||
|
||||
return acc
|
||||
},
|
||||
{} as Record<string, string[]>
|
||||
)
|
||||
return acc
|
||||
}, {} as Record<string, string[]>)
|
||||
|
||||
const validKeys = Object.values(TaxRateRuleReferenceType)
|
||||
const numberOfTargets = Object.keys(groupedRules).map((key) =>
|
||||
@@ -282,6 +279,9 @@ const useReferenceValues = (
|
||||
{
|
||||
id: ids.slice(0, DISPLAY_OVERRIDE_ITEMS_LIMIT),
|
||||
limit: DISPLAY_OVERRIDE_ITEMS_LIMIT,
|
||||
// TODO: Remove exclusion once we avoid including unnecessary relations by default in the query config
|
||||
fields:
|
||||
"-type,-collection,-options,-tags,-images,-variants,-sales_channels",
|
||||
},
|
||||
{
|
||||
enabled: !!ids.length && type === TaxRateRuleReferenceType.PRODUCT,
|
||||
|
||||
Reference in New Issue
Block a user