relay
relay copied to clipboard
@catch doesn't work on fragment root of useRefetchableFragment nor usePaginationFragment
Hey
Unfortunately there are issues with @catch in combination with useRefetchableFragment and usePaginationFragment.
On a surface level, there is no issue, until refetch or loadNext is called. When these functions are called, everything goes boom.
Given a component like this here, refetch only works when the id is manually provided. And the loadNext function doesn't work at all.
import { graphql, usePaginationFragment } from "@segments/relay";
import { type FunctionComponent, startTransition } from "react";
import type { brandForumContextCommunityDiscussionsList$key } from "./__generated__/brandForumContextCommunityDiscussionsList.graphql.ts";
import type {
brandForumContextCommunityDiscussionsListRefetchQuery,
ProductListSortOrder,
} from "./__generated__/brandForumContextCommunityDiscussionsListRefetchQuery.graphql.ts";
interface IBrandForumContextCommunityDiscussionsListProps {
brandKey: brandForumContextCommunityDiscussionsList$key;
}
export const BrandForumContextCommunityDiscussionsList: FunctionComponent<
IBrandForumContextCommunityDiscussionsListProps
> = ({ brandKey }) => {
const {
data: brand,
loadNext,
refetch,
} = usePaginationFragment<
brandForumContextCommunityDiscussionsListRefetchQuery,
brandForumContextCommunityDiscussionsList$key
>(
graphql`
fragment brandForumContextCommunityDiscussionsList on Brand
@argumentDefinitions(
first: { type: "Int", defaultValue: 5 }
after: { type: "String" }
order: { type: "ProductListSortOrder", defaultValue: AVAILABILITY }
)
@refetchable(
queryName: "brandForumContextCommunityDiscussionsListRefetchQuery"
)
@catch {
products(first: $first, after: $after, order: $order)
@connection(key: "brandForumContextCommunityDiscussionsList_products")
@required(action: THROW) {
edges @required(action: THROW) {
node {
id
name
}
}
}
}
`,
brandKey,
);
if (!brand.ok) {
throw new Error("Simple here to demo purpose");
}
const onOrderToggle = (order: ProductListSortOrder) => {
startTransition(() => {
refetch({
// 👇 When the id is not manually provided, this will result in a runtime error
id: brand.value.id,
order,
});
});
};
return (
<>
<button onClick={() => onOrderToggle("HIGHEST_PRICE")}>
Change sort
</button>
<ul>
{brand.value.products.edges.map((edge) => (
<li key={edge.node.id}>{edge.node.name}</li>
))}
</ul>
{/* 👇 When loadNext is called, this will execute the refetch query with id: null */}
<button onClick={() => loadNext(2)}>Load more</button>
</>
);
};
The expectation for this would be that it just works as expected or that the relay compiler tells us that using @catch is not allowed here.