Ergonomic React Queries
This post is mostly for future me as I’ve done this on a few projects, but for some reason keep reverting back to a suboptimal pattern.
I use React and react-query a LOT. It’s the only way to fly when it comes to keeping state in a React app. The defaults and ability to easily cache and invalidate responses saves me a TON of time in every projects while still providing a great user experience.
However, I often make it a little harder on myself than it needs to be. I blame some mild PTSD from my early days getting used to React hooks.
Filesystem Layout
To give you some more context, most of my projects have a file system layout like this.
So 99% of the time my queries are being used from either components or views. Mostly views.
The Bad Pattern
You can read up more on how react-query works, but here is an example of the “bad pattern”. Ok it’s no bad, it’s just not great. This is my first inclination, but it leads to lots of subtle bugs around mistakes in your query keys and query options.
I’m sad to report I’ve spent many hours hunting bugs that ended up being the difference between
["users", 14]
and ["user", 14]
. Not to mention finding these from teammates.
// In FolderList.jsx
import React from 'react'
import { useQuery } from "@tanstack/react-query"
import { Link } from "react-router-dom"
import { getFolders } from "../../queries/folders"
export const FolderList = () => {
const folders = useQuery({
queryKey: ["folders"],
queryFn: getVendors,
staleTime: 60 * 1000 * 2,
cacheTime: 60 * 1000 * 5,
})
// ...
}
Here we’re direclty importing useQuery()
, our fetching function, and settings
options. And we have to repeat this all over the place, anywhere we’re grabbing
our list of folders from the API.
The Good Pattern
I’m not sure why I have this ingrained feeling that hooks are different. The better
pattern is to define all of this in queries/folders.js
and just return it.
Isn’t that so much nicer?
Frank Wiles
Founder of REVSYS and former President of the Django Software Foundation . Expert in building, scaling and maintaining complex web applications. Want to reach out? Contact me here or use the social links below.