Skip to content

Instantly share code, notes, and snippets.

@dovranJorayev
Created July 8, 2024 16:22
Show Gist options
  • Save dovranJorayev/8396bf13428ec5a574a1ae19a5c81bce to your computer and use it in GitHub Desktop.
Save dovranJorayev/8396bf13428ec5a574a1ae19a5c81bce to your computer and use it in GitHub Desktop.
Util to create query instance in mobx primitives
import {
DefaultError,
QueryClient,
QueryKey,
QueryObserver,
QueryObserverResult,
UseBaseQueryOptions,
UseQueryOptions,
notifyManager,
} from '@tanstack/react-query';
import { IResource, fromResource } from 'mobx-utils';
export type QueryResultResource<TData, TError = Error> = IResource<
QueryObserverResult<TData, TError>
>;
export function fromQuery<
TQueryFnData = unknown,
TError = DefaultError,
TData = TQueryFnData,
TQueryKey extends QueryKey = QueryKey
>(
client: QueryClient,
options: UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>
): QueryResultResource<TData, TError>;
export function fromQuery<
TQueryFnData = unknown,
TError = DefaultError,
TData = TQueryFnData,
TQueryKey extends QueryKey = QueryKey
>(
client: QueryClient,
options: UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>
): QueryResultResource<TData, TError> {
// eslint-disable-next-line @typescript-eslint/no-empty-function
let unsubscribe = () => {};
// Prepare options to observer
const defaultedOptions = client.defaultQueryOptions(
options as UseBaseQueryOptions<TQueryFnData, TError, TData, TQueryKey>
);
if (!defaultedOptions.suspense) {
if (typeof defaultedOptions.staleTime !== 'number') {
defaultedOptions.staleTime = 1000;
}
}
const observer = new QueryObserver(client, defaultedOptions);
return fromResource<QueryObserverResult<TData, TError>>(
(sink) => {
/**
* Sync initial state. This is a simplified version of the logic in useBaseQuery from react-query repo.
* @link https://github.com/TanStack/query/blob/main/packages/react-query/src/useBaseQuery.ts#L125
*/
const optimisticResult = observer.getOptimisticResult(defaultedOptions);
const result = !defaultedOptions.notifyOnChangeProps
? observer.trackResult(optimisticResult)
: optimisticResult;
sink(result);
unsubscribe = observer.subscribe(
notifyManager.batchCalls((updatedResult) => {
sink(updatedResult);
})
);
},
() => unsubscribe(),
observer.getCurrentResult()
);
}
@dovranJorayev
Copy link
Author

// model.ts
const getSomeListQuery = fromQuery(client, {....});

export const model = { getSomeListQuery } 

// ui.tsx
export const View = observer(() => {
    const { data } = getSomeListQuery.current(); // Will trigger the request
    ....
})

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment