-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
Description
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.