Skip to content
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

How to Refetch Queries After Mutation in Relay? #4870

Open
devKangMinHyeok opened this issue Dec 30, 2024 · 1 comment
Open

How to Refetch Queries After Mutation in Relay? #4870

devKangMinHyeok opened this issue Dec 30, 2024 · 1 comment

Comments

@devKangMinHyeok
Copy link

devKangMinHyeok commented Dec 30, 2024

Issue: How to Refetch Queries After Mutation in Relay?

I referred to the Relay Docs - Refreshing Queries for refreshing queries. However, I need clarification on how to refetch a query in the following use case where a mutation updates data, and the query needs to be refreshed afterward.

Below is the setup I'm working with:

ListComponent

The ListComponent contains a refresh function that updates queryOptions to refetch the query with a new fetchKey and fetchPolicy.

/**
 * ListComponent.js
 */
const ListComponentQuery = require('__generated__/AppQuery.graphql');

function ListComponent(props: Props) {
  const variables = {id: '4'};
  const [refreshedQueryOptions, setRefreshedQueryOptions] = useState(null);

  const refresh = useCallback(() => {
    setRefreshedQueryOptions(prev => ({
      fetchKey: (prev?.fetchKey ?? 0) + 1,
      fetchPolicy: 'network-only',
    }));
  }, []);

  return (
    <React.Suspense fallback="Loading query...">
      <MainContent
        refresh={refresh}
        queryOptions={refreshedQueryOptions ?? {}}
        variables={variables}
      />
    </React.Suspense>
  );
}

MainContent

The MainContent uses useLazyLoadQuery to fetch data and renders it. The refresh function is called to refetch the query.

/**
 * MainContent.react.js
 */

function MainContent(props) {
  const {refresh, queryOptions, variables} = props;
  const data = useLazyLoadQuery(
    graphql`
      query AppQuery($id: ID!) {
        user(id: $id) {
          name
          friends {
            count
          }
        }
      }
    `,
    variables,
    queryOptions,
  );

  return (
    <>
      <h1>{data.user?.name}</h1>
      <div>Friends count: {data.user.friends?.count}</div>
      <Button onClick={() => refresh()}>
        Fetch latest count
      </Button>
    </>
  );
}

CreateItemButton

I want to perform a mutation and then refresh the query in ListComponent. Here's an example mutation setup:

/**
 * CreateItemButton.react.js
 */

function CreateItemButton({refresh}) {
  const [commitMutation] = useMutation(
    graphql`
      mutation CreateItemMutation($input: CreateItemInput!) {
        createItem(input: $input) {
          item {
            id
            name
          }
          user {
            id
            friends {
              count
            }
          }
        }
      }
    `,
  );

  const handleCreateItem = () => {
    commitMutation({
      variables: {
        input: { /* mutation input */ },
      },
      onCompleted: () => {
        // Refresh the query after the mutation completes
        // HOW CAN I DO THIS?
        refresh();
      },
      onError: (error) => {
        console.error(error);
      },
    });
  };

  return (
    <Button onClick={handleCreateItem}>
      Create Item
    </Button>
  );
}

And I’m curious about how to handle the case when this Button is not a child node of ListComponent but is at the same level or a parent node.

Question

How can I effectively refresh the query after the mutation in this setup? Specifically:

Is useLazyLoadQuery the best approach here, or should I use another API like useFragment or useRefetchableFragment?
Is there a better pattern to refetch queries post-mutation in Relay?

I appreciate any guidance or best practices for handling this scenario.

@captbaritone
Copy link
Contributor

The main pattern I've seen is to structure the data you want to refetch (up to, and including the whole query) as fragment which you then spread in as part of the mutation response. This ensures the data you want refetched is always refetched without introducing an additional roundtrip to the server.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants