Using Tanstack Query from Clojurescript
Intro to Tanstack Query (a.k.a React Query)
Tanstack Query (a.k.a React Query) is a tool which is loved in the react ecosystem. It has many benefits like:
- Caching requests throughout pages
- Automatic re-fetching
- Re-fetching on focus
- Support for Suspense and server streaming
Problem
We cannot use it directly in ClojureScript because the CommonJS files that Tanstack Query uses contain the private property class notation.
This happens because ClojureScript uses the Google Closure Compiler behind the scenes to interact with the JS ecosystem. The Closure compiler doesn't support public or private class fiels and this is why you will get an error like this:
Failed to inspect file
/node_modules/@tanstack/query-core/build/modern/onlineManager.cjs
Errors encountered while trying to parse file
/node_modules/@tanstack/query-core/build/modern/onlineManager.cjs
{:line 30, :column 2, :message "'}' expected"}
Solution
Step 1: Make required file changes
Go into node_modules/@tanstack/query-core/build/modern
and replace all private fields from all the .cjs
(commonjs) files:
class MyClass {
- #privateField
+ privateField
}
Step 2: Use patch-package to create a permanent patch file
From your project's root directory, run:
npx patch package @tanstack/query-core
Note that we patch
@tanstack/query-core
and not@tanstack/react-query
. The react query package usesquery-core
underneath since it targets multiple rendering libraries (Vue, Svelte etc.)
If everything goes well you should see
patch-package 8.0.0
• Creating temporary folder
• Installing @tanstack/query-core@5.40.0 with npm
• Diffing your files with clean files
✔ Created file patches/@tanstack+query-core+5.40.0.patch
And a directory patches
should be created in your project root with
the associated git patch inside. It should look something like this.
Step 3: Making changes permanent for your repository
I advise you use a static version of @tanstack/react-query
. The solution above works for version 5.40.1
:
"dependencies": {
...
"@tanstack/react-query": "5.40.1",
...
}
Follow the steps outlined in the patch-package
README:
- Add
patch-package
as apostinstall
script in yourpackage.json
"scripts": {
...
"postinstall": "patch-package"
},
- Install
patch-package
as a dev dependency
npm i -D patch-package
Now every time you will run npm install
, the git patch will be applied to make the library work correctly with ClojureScript.
Step 3: Import @tanstack/react-query
to your app
(ns query
(:require
["@tanstack/react-query" :as rq]))
(defn use-query
"Wrap useQuery
`query-key` query key array
`query-fn` query function to fetch data"
[{:keys [query-key query-fn]}]
(let [result (rq/useQuery #js {:queryFn query-fn
:queryKey (into-array query-key)})]
{:data result.data
:error? result.isError
:success? result.isSuccess
:loading? result.isLoading}))
(defonce query-client (rq/QueryClient.))
(defui query-client-provider
[{:keys [children]}]
($ rq/QueryClientProvider {:client query-client}
children))
(defhook use-get-user
[]
(use-query {:query-key [:user]
:query-fn get-user}))
Conclusion
(TanStack) react query is a great tool and should see more usage in the Clojure ecosystem however ClojureScript doesn't yet have full support for JS class syntax so we have to adapt in the meantime
Big thanks to Toni Väisänen for showing me the correct solution for this issue and big thanks to Juho Teperi (Reagent maintainer) for coming up with the original solution.
I hope this has been helpful to you.