Open ericledonge opened 9 months ago
I can confirm the react-query-native-devtools plugin does not work properly with tanstack/query v5. When trying to use it in my own project with the latest v5 release, I ran into the same error reported:
"TypeError: Cannot read properties of undefined (reading 'length') at getObserversCounter"
This occurred for me in Flipper after upgrading from tanstack/query v4 to v5. Downgrading back to v4 resolved the issue, so it seems there is an incompatibility introduced in v5 that is causing problems for the plugin.
I'm reporting this here to help add another confirmation of the problem. Hopefully more visibility on the incompatibility will help get it resolved sooner. I find this plugin invaluable for debugging and monitoring React Query in my React Native apps, so I'm eager to get it working again with the latest TanStack release.
Thanks for building this great tool.
Check null before variable access to solve the bag issue.
@sairus2k @ericledonge you can check it in this Flipper plugin file
flipper-plugin-react-query-native-devtools-v4.1.4.tgz
you can install it in your Flipper
@YOEL311 It works for me, thanks!
The above fix allowed the plugin to start functioning again, but now it's revealing that the query status + active states are all showing as inactive and false, respectively.
Think there might be a deeper issue here caused by the V5 changes @YOEL311
hey @joshsmith-watchbox I checked that It happened because the react-query data changed I attached the data with react-query V4 and react-query V5
the react-query-native-devtools
library get event from the react-query
withqueryCache.subscribe
to send it to flipper
but the data of the event is changed
this old data that get in an event in react-query-V4
you can see it contains an observes array with an option object Inside (that contains the enable field -inactive)
{
"abortSignalConsumed": true,
"cache": {
"config": {},
"listeners": [
[Function anonymous
]
],
"queries": [
[Circular
]
],
"queriesMap": {
"[\"EXAMPLE_KEY\",{\"user\":3}]": [Circular
]
},
"subscribe": [Function bound subscribe
]
},
"cacheTime": 300000,
"defaultOptions": undefined,
"gcTimeout": 67,
"initialState": {
"data": undefined,
"dataUpdateCount": 0,
"dataUpdatedAt": 0,
"error": null,
"errorUpdateCount": 0,
"errorUpdatedAt": 0,
"fetchFailureCount": 0,
"fetchMeta": null,
"fetchStatus": "idle",
"isInvalidated": false,
"status": "loading"
},
"isFetchingOptimistic": false,
"logger": {
"error": [Function anonymous
],
"log": [Function anonymous
],
"warn": [Function anonymous
]
},
"meta": undefined,
"observers": [ // <- observers array
{
"client": [QueryClient
],
"currentQuery": [Circular
],
"currentQueryInitialState": [Object
],
"currentRefetchInterval": false,
"currentResult": [Object
],
"currentResultOptions": [Object
],
"currentResultState": [Object
],
"listeners": [Array
],
"options": // <- options object
{
"_defaulted": true,
"_optimisticResults": "optimistic",
"enabled": true, // <- enabled
"queryFn": [Function queryFn
],
"queryHash": "[\"EXAMPLE_KEY\",{\"user\":3}]",
"queryKey": [
"EXAMPLE_KEY",
{
"user": 3
}
],
"refetchOnReconnect": true,
"retry": 0,
"staleTime": Infinity,
"useErrorBoundary": false
},
"previousQueryResult": undefined,
"refetch": [Function bound refetch
],
"remove": [Function bound remove
],
"selectError": null,
"subscribe": [Function bound subscribe
],
"trackedProps": [Set
]
}
],
"options": {
"_defaulted": true,
"_optimisticResults": "optimistic",
"enabled": true,
"queryFn": [Function queryFn
],
"queryHash": "[\"EXAMPLE_KEY\",{\"user\":3}]",
"queryKey": [
"EXAMPLE_KEY",
[Object
]
],
"refetchOnReconnect": true,
"retry": 0,
"staleTime": Infinity,
"useErrorBoundary": false
},
"promise": {
"_h": 1,
"_i": 1,
"_j": {
"title": "response.title"
},
"_k": null
},
"queryHash": "[\"EXAMPLE_KEY\",{\"user\":3}]",
"queryKey": [
"EXAMPLE_KEY",
{
"user": 3
}
],
"retryer": {
"cancel": [Function cancel
],
"cancelRetry": [Function cancelRetry
],
"continue": [Function _continue
],
"continueRetry": [Function continueRetry
],
"promise": {
"_h": 1,
"_i": 1,
"_j": [Object
],
"_k": null
}
},
"revertState": {
"data": undefined,
"dataUpdateCount": 0,
"dataUpdatedAt": 0,
"error": null,
"errorUpdateCount": 0,
"errorUpdatedAt": 0,
"fetchFailureCount": 0,
"fetchMeta": null,
"fetchStatus": "idle",
"isInvalidated": false,
"status": "loading"
},
"state": {
"data": {
"title": "response.title"
},
"dataUpdateCount": 1,
"dataUpdatedAt": 1701895085093,
"error": null,
"errorUpdateCount": 0,
"errorUpdatedAt": 0,
"fetchFailureCount": 0,
"fetchMeta": null,
"fetchStatus": "idle",
"isInvalidated": false,
"status": "success"
}
}
but in react-query-V5
we do not get the observer array at all
// V 5
{
"gcTime": 300000,
"isFetchingOptimistic": false,
"options": {
"_defaulted": true,
"_optimisticResults": "optimistic",
"enabled": true,
"queryFn": [Function queryFn
],
"queryHash": "[\"EXAMPLE_KEY\",{\"user\":3}]",
"queryKey": [
"EXAMPLE_KEY",
[Object
]
],
"refetchOnReconnect": true,
"retry": 0,
"staleTime": Infinity,
"throwOnError": false
},
"queryHash": "[\"EXAMPLE_KEY\",{\"user\":3}]",
"queryKey": [
"EXAMPLE_KEY",
{
"user": 3
}
],
"state": {
"data": {
"title": "response.title"
},
"dataUpdateCount": 1,
"dataUpdatedAt": 1701894630567,
"error": null,
"errorUpdateCount": 0,
"errorUpdatedAt": 0,
"fetchFailureCount": 0,
"fetchFailureReason": null,
"fetchMeta": null,
"fetchStatus": "idle",
"isInvalidated": false,
"status": "success"
}
}
is very odd because in react-query
code you can see the type of the notify
function get event with this type QueryCacheNotifyEvent
that contain observers
notify(event: QueryCacheNotifyEvent) {
notifyManager.batch(() => {
this.listeners.forEach((listener) => {
listener(event)
})
})
}
export type QueryCacheNotifyEvent =
| NotifyEventQueryAdded
...
interface NotifyEventQueryAdded extends NotifyEvent {
type: 'added'
query: Query<any, any, any, any>
}
export class Query<
TQueryFnData = unknown,
TError = DefaultError,
TData = TQueryFnData,
TQueryKey extends QueryKey = QueryKey,
> extends Removable {
queryKey: TQueryKey
queryHash: string
options!: QueryOptions<TQueryFnData, TError, TData, TQueryKey>
...
#observers: Array<QueryObserver<any, any, any, any, any>>
I think I have found the problem. this Query class in react-query V5
export class Query<
TQueryFnData = unknown,
TError = DefaultError,
TData = TQueryFnData,
TQueryKey extends QueryKey = QueryKey,
> extends Removable {
queryKey: TQueryKey
queryHash: string
options!: QueryOptions<TQueryFnData, TError, TData, TQueryKey>
state: QueryState<TData, TError>
isFetchingOptimistic?: boolean
#initialState: QueryState<TData, TError>
#revertState?: QueryState<TData, TError>
#cache: QueryCache
#promise?: Promise<TData>
#retryer?: Retryer<TData>
#observers: Array<QueryObserver<any, any, any, any, any>>
#defaultOptions?: QueryOptions<TQueryFnData, TError, TData, TQueryKey>
#abortSignalConsumed: boolean
and this Query class in V4
export class Query<
TQueryFnData = unknown,
TError = unknown,
TData = TQueryFnData,
TQueryKey extends QueryKey = QueryKey,
> extends Removable {
queryKey: TQueryKey
queryHash: string
options!: QueryOptions<TQueryFnData, TError, TData, TQueryKey>
initialState: QueryState<TData, TError>
revertState?: QueryState<TData, TError>
state: QueryState<TData, TError>
isFetchingOptimistic?: boolean
private cache: QueryCache
private logger: Logger
private promise?: Promise<TData>
private retryer?: Retryer<TData>
private observers: QueryObserver<any, any, any, any, any>[]
private defaultOptions?: QueryOptions<TQueryFnData, TError, TData, TQueryKey>
private abortSignalConsumed: boolean
Maybe changing the data type of the 'observers' property can make a difference.
Hi, I also have this problem. Please let me know when fixed.
Is there any plan to release at least v4.1.4
that just makes the flipper plugin work (to show queries and its data)?
Is there any plan to prepare a new version and release (let's say 5.0.0
) that is fully compatible with query v5 and does not have that status
field bug and other mentioned issues above?
Does anyone work on any of these 2 topics?
cc: @bgaleotti
@anton-patrushev I took a look at the latest Tanstack docs, and it has been updated with a reference to a separate plugin that supports React Query v5: react-native-react-query-devtools.
It does appear there is a requirement of being on React Native 0.73.2 or above and React Query 5.17.19 or above. Still, might be worth a look as an alternative to this library until support for React Query v5 is added.
hey @joshsmith-watchbox
BTW, this is actually what I end up with for dubbing and inspecting tanstack query
But this not definitely not ideal and not what we want — I would rather have a flipper tool for that to have all my debugging things there instead of in-app view.
From the other side, my main concern is about flipper + react-native future — sounds like the react-native team is moving in a different direction — and that would certainly cause another way of thinking in the community. So we may not see a flipper as the popular debugging tool for react-native apps.
I was trying to use it with TanStack v5 but it wasn't working.
I've downgraded to v4 and it's working.
Thank you for your work! This plugin is a must have for us!