T
TanStack15mo ago
adverse-sapphire

queryClient.fetchQuery persister

Hey guys, I have setup a mobile app using Capacitor and Ionic, and I'm using react-query to manage my API calls. I created an asyncStoragePersister using a cordova sqlite plugin to store the cache on the mobile phone and allow offline usage of the app without having to persist data myself. It seems to work pretty well. The problem is, my app is protected by an auth, and I have to add my user profile fetch in this auth setup, which is outside React (not a component). After some look, I find that I can use react-query outside of a component using my queryClient which I export, with a fetchQuery. I managed to make it work, but it doesn't use the persister since it is not declared inside the queryClient itself but in the react-query context. Is there any way to also stick my persister to the queryClient when used outside of react ? Thanks.
10 Replies
adverse-sapphire
adverse-sapphireOP15mo ago
persister:
const store = new Storage({
driverOrder: [CordovaSQLiteDriver._driver],
})
store
.defineDriver(CordovaSQLiteDriver)
.then(() => {
store
.create()
.then(() => {
console.log("Storage is ready")
})
.catch(err => {
console.error("Storage is not ready:", err)
})
})
.catch(err => {
console.error("Storage driver is not ready:", err)
})

const DataStoragePersister: AsyncStorage = {
getItem(key: string) {
return store.get(key)
},
setItem(key: string, value: any) {
return store.set(key, value)
},
removeItem(key: string) {
return store.remove(key)
}
}

export default createAsyncStoragePersister({
storage: DataStoragePersister
})
const store = new Storage({
driverOrder: [CordovaSQLiteDriver._driver],
})
store
.defineDriver(CordovaSQLiteDriver)
.then(() => {
store
.create()
.then(() => {
console.log("Storage is ready")
})
.catch(err => {
console.error("Storage is not ready:", err)
})
})
.catch(err => {
console.error("Storage driver is not ready:", err)
})

const DataStoragePersister: AsyncStorage = {
getItem(key: string) {
return store.get(key)
},
setItem(key: string, value: any) {
return store.set(key, value)
},
removeItem(key: string) {
return store.remove(key)
}
}

export default createAsyncStoragePersister({
storage: DataStoragePersister
})
My profile fetch function:
async function getUser() {
try {
const { data }: {data: AppUserWithRolesPreferences} = await queryClient.fetchQuery({
queryKey: ["user"],
queryFn: async () => await axios.get(`${import.meta.env.VITE_API_URL}/auth/postLogin`),
})

console.log("fetching user", data)

useUserStore.setState({ user: data, initialized: true })
} catch (e) {
useUserStore.setState({ user: null, initialized: true })
}
}
async function getUser() {
try {
const { data }: {data: AppUserWithRolesPreferences} = await queryClient.fetchQuery({
queryKey: ["user"],
queryFn: async () => await axios.get(`${import.meta.env.VITE_API_URL}/auth/postLogin`),
})

console.log("fetching user", data)

useUserStore.setState({ user: data, initialized: true })
} catch (e) {
useUserStore.setState({ user: null, initialized: true })
}
}
stormy-gold
stormy-gold15mo ago
you need to subscribe the persister to the queryClient
stormy-gold
stormy-gold15mo ago
with persistQueryClientSubscribe: https://tanstack.com/query/v5/docs/framework/react/plugins/persistQueryClient#persistqueryclientsubscribe that's what <PersistQueryClientProvider> does for you in react
persistQueryClient | TanStack Query React Docs
This is set of utilities for interacting with "persisters" which save your queryClient for later use. Different persisters can be used to store your client and cache to many different storage layers. Build Persisters
adverse-sapphire
adverse-sapphireOP15mo ago
Okay, and if I do so, should I still give the persister to my PersistQueryClientProvider ? Or it will make some problems because of a double subscribe ? Or i can just unsubscribe after making my query ?
stormy-gold
stormy-gold15mo ago
just subscribe once with the PersistQueryClientProvider. it has an onSuccess callback for the initial restore
adverse-sapphire
adverse-sapphireOP15mo ago
okay, but does the PersistQueryClientProvider do the subscribe too ? Because if it does, I should remove it I guess ?
stormy-gold
stormy-gold15mo ago
yes it does and yes you only want to subscribe once
adverse-sapphire
adverse-sapphireOP15mo ago
Okay, and can I get issues if a query start before the subscribe or at the same time ?
stormy-gold
stormy-gold15mo ago
that's why there is the onSuccess callback
adverse-sapphire
adverse-sapphireOP15mo ago
Hmm, yeah okay, so I need to freeze the whole app while this is setting up ? (i guess it's almost instantly setup)

Did you find this page helpful?