Reputation: 24077
I'm just getting started with a new Remix app, and would like to try and understand a bit more about the data fetching approach for route components.
Let's say I have a route directory structure like so:
app
├── root.jsx
└── routes
├── sales.jsx
└── sales
└── info.jsx
So I have a sales route, /sales
which will render the sales.jsx
component. I also have a /sales/info
route which is renders the sales/info.jsx
component in the Outlet
of sales.jsx
.
Both sales.jsx
and sales/info.jsx
need the same data from an external api. So in both of their loader functions I have something like this:
export const loader: LoaderFunction = async ({ request }) => {
const salesData = await fetchSales(request);
return { salesData };
};
The loader
functions are identical for both.
This allows me the userLoaderData
the salesData
that's loaded from the api.
However, this data is fetched twice - once from sales.jsx
and also from sales/info.jsx
, even though the request is identical both times.
This seems very wasteful. My first thought is to introduce some sort of server-side caching layer to intercept the request, but my understanding is these requests happen concurrently anyway so this wouldn't help.
Does Remix have some sort of de-duping functionality or other approach to prevent fetching the same data more than once for a given route when multiple child components need the same data?
Upvotes: 0
Views: 3754
Reputation: 20312
Loaders run in parallel, so there is no way to prevent duplicate fetches.
However, it is recommended that you only fetch the data that is needed for the specific route/layout.
In your case, if you only need the sales data in the info UI (that is, you're not using it in the loader), you can use the useMatches
hook to retreive the data from the parent loader.
export default function SalesInfo() {
const infoData = useLoaderData() // data from this loader
const matches = useMatches() // matches includes all data from root to leaf route
const salesData = matches[matches.length - 2].data // get parent data
//...
}
Again, this is only available in the UI component, not the loader. If you do need the data in the loader, you will need to re-fetch it. You could use a server-side cache if the query is expensive.
Upvotes: 1