Skip to content

Add support for non-serializable query keys or memoization. #1829

@quisido

Description

@quisido

I like query keys conceptually because they act a lot like dependency arrays for built-in hooks like useMemo. As long as the dependency array doesn't change, you get the same results, except on a global scale instead of local state.

Unfortunately, query keys fail this memoization concept when it comes to non-serializable keys.

I really, really want to "cache-bust" based on a function, and I cannot for the life of me figure out how to do it well with these serializable keys, so here is a simplified example of my use case:

function App() {
  // Define a stateful/changing API endpoint.
  const [endpoint, setEndpoint] = useState('https://some-api/');

  // Execute the API based on the variable endpoint.
  const callApi = useCallback(() => {
    return fetch(endpoint);
  }, [endpoint]);

  // Pass the API function via context.
  return (
    <>
      <Toggle onChange={setEndpoint} /> // <-- set a different endpoint for the entire application
      <Api.Provider value={callApi}>
        <Child /> // <-- entire application uses the API from context
      </Api.Provider>
    </>
  );
}

Now any of the children can execute this API from the context:

function SomeChild() {
  const callApi = useContext(Api);
  const { data, error, isFetching } = useQuery(
    ['my-api'],
    async () => {
      return await callApi(); // <-- call the API, which can change
    },
    options,
  );
}

Current behavior: When Toggle changes the endpoint, thus changing the callApi function, the fetched data from the last API call remains cached and SomeChild does not rerender unless remove()/refetch() are called manually.

Desired behavior: When Toggle changes the endpoint, thus changing the callApi function, I want SomeChild's use of useQuery to drop its cache and refetch the data.

Expected implementation: Based on existing React patterns, my intuition tells me I should be able to list [callApi] as a dependency array to useQuery instead of the string 'my-api'. I would also value a onDependencyArrayChange that lets me clear the previous cache, which I no longer need.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions