Basics of react-query

Basics of react-query

Posted

If you don’t know already what react-query actually is or why you should care, let’s just say it makes your life much easier. With react-query you do not have to consider something like react context or redux to handle your fetching state.

Let’s see a quick example:

const [data, setData] = React.useState();
const [error, setError] = React.useState(null);
const [loading, isLoading] = React.useState(false);

useEffect(() => {
  const fetchData = async () => {
    setIsLoading(true);
    try {
      const res = await fetch("yourapi");
      const data = await res.json();
      setData(data);
    } catch (error) {
      setError(error);
    }
    setIsLoading(false);
  };

  fetchData();
}, []);

Bet you have done something familiar before and it gets kinda ugly pretty fast, and we have not even gotten to the ‘state’ part of it. Often you wanna pass the data around as props to other components, soon you start using context or redux for passing it around.

Before we do something with react-query we have to wrap the provider around our app.

const queryClient = new QueryClient();

return (
  <QueryClientProvider client={queryClient}>
    <YourApp />
  </QueryClientProvider>
);

Now when have that in place, let’s refactor our component using react-query.

async function fetchData() {
  const res = await fetch("your-api");
  const data = await res.json();

  return data;
}

function Component() {
  const query = useQuery(["my-data-key"], fetchData);
  // or const {data, isLoading, isError, error} = useQuery(...)

	...
}

Now we have everything we need right out of the box.

Sharing the data

If we want to share the state in the first example you would have to pass it as props all over the place.

Now, with react-query, all you have to do is to reuse the query key from the first component.

import {fetchData} from ...

function NestedComponent() {
	const query = useQuery(["my-data-key"], fetchData);

	...
}

Now you have shared state between our components.

If you have state that is dependent on variables you can just pass this to the query as props.

function NestedComponent(props) {
	const query = useQuery(["my-data-details-key", props.id], fetchData);

	...
}

function Component() {
  const query = useQuery(["my-data-details-key", 1], fetchData);

	...
	return (
		<NestedComponent id={1} />
	)
}

Now what happens if you have some other component that updates your data.

async function updateData(id) {
  const res = await fetch(`/endpoint-that-updates-details/${id}`, {
    method: "POST",
  });
  const data = await res.json();
  return data;
}

function ComponentThatUpdatesStuff(props) {
  const queryClient = useQueryClient(); // queryClient is defined in the react-query provider
  const updateQuery = useMutation((data) => updateData(props.id), {
    onSuccess: () => {
      // this will cause the other components that are using this key to refresh!
      queryClient.refetchQueries(["my-data-details-key", props.id]);
    },
  });
}

This was a short and simple?! introduction to react-query, I hope you got something out of it.