How to invalidate queries found on other pages?

I understand the logic of overriding queries, however it works with queries that are on the same page. When you need to invalidate a query that is on another page it does not work. For example, if I have a table that is filled with customers through a query to get all the customers. And then I go into a client’s profile, and I edit some information. If in that query to edit I invalidate the query that brings me all the clients, so that the information is refreshed with the updated information, the re-query is not done. It keeps showing me the past information and the app doesn’t really make a request again. Is this a bug? or should I do this differently?

PS: There is also a “refresh data” action, but it doesn’t work this way either.

Hi, I believe this is not supported. It may require invalidating all the queries, but I am not sure about that one either.

Even invalidating all queries still does’t function.

Can we control which queries to cache?

So basically we have no way to override queries that were made on other pages? or control how to cache the information? The issue is that if this behavior cannot be managed, we will always face outdated information. There must be a way and if not, it seems to me to be a vital functionality.

hello?

You can disable SSR for that specific page/component, that should allow you to invalidate the cache across pages.

1 Like

Can you please suggest how this can be done?
This issue still seems to be quite important and blocking. As most of the queries on other pages go stale after any change.
Let me quickly describe my use case: I have an HTTP integration, connected to a remote database, which is basically a REST API.
I have a global context, which exposes global actions (update/delete/create) for modifying the data using the correct tokens and permissions.
I have a table with a list of items, and whenever I click on a row, I go to a separate Edit page for that given item. It first fires an edit action and then invalidates queries through the Refresh action.
But the queries are not refreshed on another page, the data is stale.

Maybe there is another way around this issue besides disabling SSR?

unfortunately i was not able to hear back from the team, or to find something remotely similar to what i need, so i came up with a quick hack which would do the trick for next next few weeks and unblock our team.
In short gist - i just manually fire plasmicInvalidate on the page that i land after my form finishes doing it’s thing. Therefore i am able to update the query on another page After the redirect has happened, by tracking whether I need to do it (there is a variable in a context called lastUpdatedPath).
The ugly thing here is that without setTimeout it does not work for some reason, because of some internal mechanisms of usePlasmicDataOp hook. Would gladly hear some feedback of how this solution can be improved.

import React, { useState, useContext, useCallback, PropsWithChildren } from 'react';
import { usePlasmicInvalidate } from '@plasmicapp/react-web/lib/data-sources';
import { useRouter } from 'next/router';

// Create a context
const RevalidateContext = React.createContext({
  lastUpdatedPath: '',
  revalidate: (resetLastUpdatedPath: boolean) => {},
});

// Provider component
export const RevalidateProvider = ({ children }: PropsWithChildren) => {
  // track last place where we actually triggered a revalidation.
  // only do it twice - once after invalidation, and second one - after a redirect to the page where 
  // we need to refresh the table.
  const [lastUpdatedPath, setLastUpdatedPath] = useState('');
  const invalidateQuery = usePlasmicInvalidate();
  const router = useRouter();

  // Function to revalidate and update the key
  const revalidate = useCallback(async (resetLastUpdatedPath?: boolean) => {
    await invalidateQuery(['plasmic_refresh_all']);
    if (resetLastUpdatedPath) {
      setLastUpdatedPath('');
    } else {
      setLastUpdatedPath(router?.pathname);
    }
  }, [invalidateQuery, router?.pathname]);

  // Context value
  const value = { revalidate, lastUpdatedPath };

  return (
    <RevalidateContext.Provider value={value}>
      {children}
    </RevalidateContext.Provider>
  );
};

// Custom hook to use the revalidation context
export const useRevalidate = () => {
  const context = useContext(RevalidateContext);
  if (!context) {
    throw new Error("useRevalidate must be used within a RevalidateProvider");
  }
  return context;
};

Here is how it is used within _app.tsx

  const { revalidate, lastUpdatedPath } = useRevalidate();
  const router = useRouter();

  React.useEffect(() => {
    if (lastUpdatedPath && lastUpdatedPath !== router?.pathname) {
      setTimeout(() => {
        revalidate(true);
      }, 1500);
    }
  }, [router?.pathname, lastUpdatedPath]);

And whenever you fire a global action that is provided by your global context

  const onBeforeAction = (call: any) => async (...args: any) => {
    const resp = await call(...args);
    revalidate(false);

    return resp;
  } 
  const actions = useMemo(() => ({
    update: onBeforeAction(api.update),
    delete: onBeforeAction(api.delete),
    create: onBeforeAction(api.create),
  }), []);

  return (
    <GlobalActionsProvider contextName="GlobalActionsContext" actions={actions}>
...

Looks like you’re using Next.js. Most of our users use getStaticProps for static content, which will cache the props once per app build.

For app building use cases / dynamic content, you don’t want to cache the props since they change often or might need to be personalized per user. You’ll need to switch to using getServerProps instead, which will be called for every visit to a page. See Next.js docs on this topic here: Data Fetching: getServerSideProps | Next.js

Hi Jason!
Thanks for jumping in, I really appreciate it!
Yes, I am using Next.js 14.2.5 (page router version), which is the default within the boilerplate provided in the guide.
But I don’t use getStaticProps, nor do I think it would make sense to use getServerSideProps in this case.
I have a specific request from the team to be able to edit the queries within the studio, so I am limited to HTTP integrations.
Therefore I am not writing the queries by hand from within code components, or from getStaticProps - everything is happening from within the studio.
Want me to send over some implementation details?

Can you share your code that loads the Plasmic content?

sure
As an additional helpful piece of information - I’m using codegen, and import the PlasmicRootProvider from @plasmicapp/react-web

<PlasmicRootProvider Link={Link} platform={'nextjs'} Head={Head}>
    <Component {...pageProps} />
</PlasmicRootProvider>

This is a piece of code from the component created from within Plasmic studio, specifically responsible for fetching the data from the HTTP integration.

And this is how it looks like within the studio