React Query in Web Extensions
React Query is a library for fetching data from API. Is performant, manages fetched data, and what is the most important is backend agnostic — you can use it with REST or GraphQL APIs. But what about where you didn’t have API at all. Did you ever wonder “Can We use react-query when I don’t have API?”.
This post was published originally on my project Bookmarkly.app. Now when this project is retired I'm moving it to my blog.
TL;DR
A scene from Brooklyn 9–9 — great tv show :)
But, how is that possible?
As I mention above react query is backend agnostic. It’s mean it’s not worrying about how we obtain data from the backend. We just need a key that represents our data and the Promise that after resolving fetches our data.
In this example, we are using https://github.com/mozilla/webextension-polyfill to add cross-browser support.
import browser from "webextension-polyfill";
export async function getSites() {
const { sites } = await browser.storage.local.get(["sites"]);
return sites || [{ id: 1, name: "sample website" }];
}
In react component, we can use react’s fetch-as-render experimental functionality, that’s why we don’t bother catching errors in the component.
import { getSites } from './queries;
export const Sites = () => {
const { data } = useQuery('sites', getSites);
return (
<div>
{data.map(site => (
<span key={site.id}>{site.name}</span>
)}
</div>
)
}
To catch errors we are using error boundaries. We can create a sample component like this:
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
// You can also log the error to an error
// reporting service logErrorToMyService(error, errorInfo);
}
render() {
if (this.state.hasError) {
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
export ErrorBoundary;
Everything is composed like that:
import * as React from "react";
import * as ReactDOM from "react-dom";
import { ReactQueryConfigProvider } from "react-query";
import { Sites } from "./sites";
import { ErrorBoundary } from "./error-boundry";
const queryConfig = {
suspense: true,
};
async function main(): Promise<Event> {
return new Promise((resolve) =>
window.addEventListener("DOMContentLoaded", resolve)
);
}
function render() {
ReactDOM.render(
<ReactQueryConfigProvider config={queryConfig}>
<ErrorBoundary>
<Sites />
</ErrorBoundary>
</ReactQueryConfigProvider>,
document.getElementById("popup")
);
}
main()
.then(render)
.catch(reportError);
Summary
As you see, it’s easy to use react query in web extension. React Query has fantastic developer experience. You should try it yourself.