Skip to content

Getting started

Installation

Peer Dependency

@tanstack/query-core is a required peer dependency

bash
npm install @tanstack/query-core mobx-tanstack-query
bash
yarn add @tanstack/query-core mobx-tanstack-query
bash
pnpm add @tanstack/query-core mobx-tanstack-query

React Integration

This library is architecturally decoupled from React and doesn't provide React-specific hooks. For projects using React, we recommend leveraging the official @tanstack/react-query package instead. It offers first-class support for React hooks and follows modern React patterns.

The current React integration is implemented via MobX React bindings.

Creating instance of MobxQueryClient

This is extended version of original QueryClient

ts
import { MobxQueryClient } from "mobx-tanstack-query";
import { hashKey } from '@tanstack/query-core';

export const queryClient = new MobxQueryClient({
  defaultOptions: {
    queries: {
      throwOnError: true,
      queryKeyHashFn: hashKey,
      refetchOnWindowFocus: true,
      refetchOnReconnect: true,
      staleTime: 10 * 60 * 1000,
      retry: (failureCount, error) => {
        if (error instanceof Response && error.status >= 500) {
          return failureCount < 3;
        }
        return false;
      },
    },
    mutations: {
      throwOnError: true,
    },
  },
});

Writing first queries

ts
import { MobxQuery } from 'mobx-tanstack-query';

const fruitQuery = new MobxQuery({
  queryClient,
  queryFn: async ({ queryKey }) => {
    const response = await fetch(`/api/fruits/${queryKey[1]}`);
    return await response.json();
  },
  queryKey: ['fruits', 'apple'],
})

Using with classes

ts
import { observable, action } from "mobx";
import { MobxQuery } from 'mobx-tanstack-query';

class MyViewModel {
  abortController = new AbortController();

  @observable
  accessor fruitName = 'apple';

  fruitQuery = new MobxQuery({
    queryClient,
    abortSignal: this.abortController.signal, // Don't forget about that!
    queryFn: async ({ queryKey }) => {
      const response = await fetch(`/api/fruits/${queryKey[1]}`);
      return await response.json();
    },
    options: () => ({
      enabled: !!this.fruitName,
      queryKey: ['fruits', this.fruitName],
    })
  })

  @action
  setFruitName(fruitName: string) {
    this.fruitName = fruitName;
  }

  destroy() {
    this.abortController.abort();
  }
}

Using in React

tsx
import { observer } from "mobx-react-lite";

const App = observer(() => {
  return (
    <div>
      {fruitQuery.result.data?.name}
    </div>
  )
})

Released under the MIT License.