Skip to main content

Data Fetching

Catalyst provides two fetcher functions for loading data:

FetcherWhen it runs
serverFetcherOn initial page load (SSR)
clientFetcherOn client-side navigation

Basic Usage

Attach fetcher functions to your page component:

const HomePage = () => {
const { data, isFetching, error } = useCurrentRouteData();

if (isFetching) return <Loading />;
if (error) return <Error message={error.message} />;

return <div>{data.title}</div>;
};

HomePage.serverFetcher = async ({ params }) => {
const response = await fetch("https://api.example.com/data");
return response.json();
};

HomePage.clientFetcher = async ({ params }) => {
const response = await fetch("https://api.example.com/data");
return response.json();
};

export default HomePage;

Fetcher Parameters

Both fetchers receive the same parameters:

ParameterTypeDescription
routeobjectRoute object from routes array
locationLocationCurrent URL location
paramsobjectDynamic route parameters
searchParamsURLSearchParamsQuery string parameters
navigatefunctionNavigation function for redirects

Second argument contains fetcherArgs from RouterDataProvider:

HomePage.serverFetcher = async ({ params, searchParams }, { store }) => {
const page = searchParams.get("page") || 1;
return store.dispatch(fetchProducts(params.category, page));
};

Accessing Data

useCurrentRouteData

Returns data for the current route:

import { useCurrentRouteData } from "@tata1mg/router";

const ProductPage = () => {
const { data, error, isFetching, isFetched, refetch, clear } = useCurrentRouteData();

return (
<div>
{isFetching && <Spinner />}
{error && <Error message={error.message} />}
{data && <ProductDetails product={data} />}
</div>
);
};
PropertyTypeDescription
dataanyData returned by fetcher
errorErrorError thrown by fetcher
isFetchingbooleanFetch in progress
isFetchedbooleanFetch completed
refetchfunctionRe-run clientFetcher
clearfunctionClear cached data

useRouterData

Returns data for all routes in the current tree:

import { useRouterData } from "@tata1mg/router";

const Layout = () => {
const routerData = useRouterData();
// { "/dashboard": { data, error, ... }, "/dashboard/settings": { data, error, ... } }
};

Revalidation

Refetch

Re-run the clientFetcher with optional arguments:

const ProductList = () => {
const { data, refetch } = useCurrentRouteData();
const [page, setPage] = useState(1);

useEffect(() => {
refetch({ page });
}, [page]);

return <div>...</div>;
};

ProductList.clientFetcher = async ({ params }, { store }, { page = 1 }) => {
const response = await fetch(`/api/products?page=${page}`);
return response.json();
};

Clear

Remove cached data for the current route:

const { clear } = useCurrentRouteData();

useEffect(() => {
return () => clear();
}, []);

Server Fetcher Security

Code in serverFetcher is excluded from the client bundle. You can safely use:

  • Environment variables with secrets
  • Database connections
  • Internal API calls
HomePage.serverFetcher = async ({ params }) => {
// Safe: not exposed to client
const apiKey = process.env.INTERNAL_API_KEY;
const response = await fetch("https://internal-api.example.com/data", {
headers: { Authorization: `Bearer ${apiKey}` }
});
return response.json();
};