T
TanStack2d ago
unwilling-turquoise

How to wait for 'clean' queryCollection

This is related to this scenario here: https://discord.com/channels/719702312431386674/1369767025723052134/1423904416272089089. I'm creating a row if it does not already exist. If it does exist, the API will return an error, and the desired behaviour is that it refetches to sync with the query state. However, at this point the change gets reverted, triggering the same mutation to run again. I'm wondering if there's a way to wait for the collection to be 'clean': that is that there was a refetch and no errors occured since. Here's some code for context:
useEffect(() => {

// It's important for this logic to be idempotent since React will call this twice
querySubjects.forEach(async (querySubject) => {
const matchingSubject = subjectsCollection.get(querySubject.id);
if (!matchingSubject && subjectsCollection.isReady()) {
try {
subjectsCollection
.insert({
name: displayLongOrShort(querySubject.name),
subject_id: querySubject.id,
hue: Math.floor(Math.random() * 360),
})
.isPersisted.promise.catch();
} catch (error) {
/* Blanket catch in case the sync happens and there was already such a row */
}
}
});
}, [querySubjects, subjectsCollection]);
useEffect(() => {

// It's important for this logic to be idempotent since React will call this twice
querySubjects.forEach(async (querySubject) => {
const matchingSubject = subjectsCollection.get(querySubject.id);
if (!matchingSubject && subjectsCollection.isReady()) {
try {
subjectsCollection
.insert({
name: displayLongOrShort(querySubject.name),
subject_id: querySubject.id,
hue: Math.floor(Math.random() * 360),
})
.isPersisted.promise.catch();
} catch (error) {
/* Blanket catch in case the sync happens and there was already such a row */
}
}
});
}, [querySubjects, subjectsCollection]);
To give some more context, the querySubjects comes from a tanstack query on a different API I don't control.
1 Reply
unwilling-turquoise
unwilling-turquoiseOPthis hour
Also I do see that state syncing is generally undesirable, but since these are different APIs on completely different services theres not much I can do. My solution to this was to instead have these operations happen in a global QueryObserver on the data source (not the querycollection but the query i am syncing from), to the queryCollection. That way, the sync only happens on query change rather than when react chooses to re-invoke the effect.

Did you find this page helpful?