-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(vue-query): use shallowReactive and shallowReadonly to prevent performance slow down for large dataset #7733
fix(vue-query): use shallowReactive and shallowReadonly to prevent performance slow down for large dataset #7733
Conversation
…rforamcne slowdown for large datasets
6d128a1
to
5710b3d
Compare
☁️ Nx Cloud ReportCI is running/has finished running commands for commit a3f15f3. As they complete they will appear below. Click to see the status, the terminal output, and the build insights. 📂 See all runs for this CI Pipeline Execution ✅ Successfully ran 1 targetSent with 💌 from NxCloud. |
More templates
@tanstack/angular-query-devtools-experimental
@tanstack/angular-query-experimental
@tanstack/query-async-storage-persister
@tanstack/eslint-plugin-query
@tanstack/query-broadcast-client-experimental
@tanstack/query-core
@tanstack/query-devtools
@tanstack/query-persist-client-core
@tanstack/query-sync-storage-persister
@tanstack/react-query
@tanstack/react-query-next-experimental
@tanstack/react-query-devtools
@tanstack/react-query-persist-client
@tanstack/solid-query
@tanstack/solid-query-devtools
@tanstack/solid-query-persist-client
@tanstack/svelte-query
@tanstack/svelte-query-devtools
@tanstack/svelte-query-persist-client
@tanstack/vue-query
@tanstack/vue-query-devtools
commit: |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #7733 +/- ##
===========================================
+ Coverage 44.56% 71.51% +26.95%
===========================================
Files 185 19 -166
Lines 7062 481 -6581
Branches 1552 136 -1416
===========================================
- Hits 3147 344 -2803
+ Misses 3552 107 -3445
+ Partials 363 30 -333
|
I'm fine with People just tried to modify returned data and opened bug reports that they can't. Maybe we could achieve this conditionally by introducing some kind of |
@DamianOsipiuk In react-query, the Otherwise, providing kind of |
it would be nice to mark readonly only in development mode |
will there be an advantage if you immediately use shallowRef, without casting toRefs? |
It can also be used in useMutationState import { hasChanged } from '@vue/shared'
import { type Ref, customRef } from 'vue'
type Dispatch<A> = (value: A) => void
type SetStateAction<S> = S | ((prevState: S) => S)
/**
* Returns a stateful value, and a function to update it.
*/
export function useState<S>(initialState: S | (() => S)): [Readonly<Ref<S>>, Dispatch<SetStateAction<S>>]
// convenience overload when first argument is omitted
/**
* Returns a stateful value, and a function to update it.
*/
export function useState<S = undefined>(): [Readonly<Ref<S | undefined>>, Dispatch<SetStateAction<S | undefined>>]
export function useState(initialState?: unknown) {
let value = typeof initialState === 'function' ? initialState() : initialState
let _trigger = () => {}
const state = customRef((track, trigger) => {
_trigger = trigger
return {
get() {
track()
return value
},
set() {
console.error('state is readonly')
},
}
})
const setState = (newValue: unknown) => {
const _newValue = typeof newValue === 'function' ? newValue(value) : newValue
if (hasChanged(value, _newValue)) {
value = _newValue
_trigger()
}
}
return [state, setState]
} const [state, setState] = useState<number>() |
In
@teleskop150750 |
why didn't you want to use readonly only in dev mode? |
@teleskop150750 @DamianOsipiuk , any thoughts on this PR? Should be closed or can be complemented? |
In the examples given, vue/core, I also meant shallowReadonly. Still, I'm inclined to make it only in dev mode. The vue/core example is a good argument. In any case, shallowReadonly will not eliminate some violations of the rules specified in the documentation. Therefore, it makes no more sense to send it into production. Some tanstack/query implementations in other frameworks do not worry about this and leave it to the developer's responsibility. |
@teleskop150750 Yes, I agree with you about using shallowReadonly only in dev mode like vue/core example.(I thought about using deep readonly 😅)
Agree, this is the reason that I think we can remove deep readonly(and also shallow readonly in prod you suggested) in vue-query code base |
I would still like to get Stripping |
example: if you use // packages/vue-query/src/useBaseQuery.ts
import type { DeepReadonly } from 'vue-demi'
export function useBaseQuery(): DeepReadonly<UseBaseQueryReturnType<TData, TError>>
// 105 line
const observer = new Observer(client, defaultedOptions.value)
type WrapInRef<T> = {
[K in keyof T]: T[K] extends Function ? T[K] : Ref<T[K]>;
};
type State = WrapInRef<QueryObserverResult<TData, TError>>;
const rawState = observer.getCurrentResult()
const state = rawStateToState(rawState)
function rawStateToState(payload: QueryObserverResult<TData, TError>): State {
const ret: any = {}
for (const key of Object.keys(payload) as Array<keyof QueryObserverResult<TData, TError>>) {
if (typeof payload[key] === 'function') {
ret[key] = payload[key]
} else {
ret[key] = shallowRef(payload[key])
}
}
return ret
}
let unsubscribe = () => {
// noop
}
// .....
const object = state as unknown as UseBaseQueryReturnType<TData, TError>
object.suspense = suspense
object.refetch = refetch
return object as DeepReadonly<UseBaseQueryReturnType<TData, TError>> function updateQueryState(payload: State, update: QueryObserverResult<TData, TError>) {
for (const key of Object.keys(update) as Array<keyof QueryObserverResult<TData, TError>>) {
if (typeof update[key] === 'function') {
continue
}
(payload[key] as any).value = update[key]
}
} |
@wns3645 Could you check if latest package from this PR works well with |
@DamianOsipiuk |
Thank you for this 🌻 I am wondering if there is a specific reason why the
|
…nu>` * fix new page or query won't update menu items by replace the prop `postPages` with `queryParam` for passing it as the `queryKey` of `useApiPosts()` to sync `data` with `pages/posts.vue` * now will only expand menus of the current and previous cursor when pages get updated as currently it's not possible to move page backwards @ `<PostNav>` * now will display `H3Error.toJSON()` & `Error.stack` which is in html string: https://github.com/nuxt/nuxt/blob/fcf023e611efb662124164b5cbcae12503b0ee0a/packages/nuxt/src/core/runtime/nitro/error.ts#L19 * wrapping with a new root level `div.container` @ error.vue * partial revert 9046c33 due to TanStack/query#7733 @ `<PostRendererList>` @ fe
Use
shallowReactive
andshallowReadonly
instead ofreactive
andreadonly
reactive
andreadonly
uses deep conversion which affects all nested properties. Therefore, performance slows when the data is a large array of deeply nested objects.shallowReactive
is enough because we need reactivity for only shallow properties(i.e., properties at the first depth).Although
shallowReadonly
cannot strictly prevent mutating deeply nested properties, it would be enough as ref values returned from third-party composables are expected not to change directly.