Loaders and Data Fetching in routes.json
This document explains how to configure and use loaders, actions, and handle server-side and client-side code separation in your routes using the routes.json
file.
Server-Side Loaders
Server-side loaders are used to fetch data on the server before rendering a component. They are configured using the hasLoader
field in routes.json
. By default, server-side code must be located in files ending with .server.js
for security and performance reasons.
Syntax
{
"/path": {
"hasLoader": true,
"componentPath": "@adminide-stack/user-auth0/lib/components/callback.server.js"
}
}
Implementation
When hasLoader
is set to true
, you need to implement a loader function in your route file:
export const loader = async ({ params, context }) => {
// Fetch data here
return { data };
};
Handling Component with server code by using hasServerCode
Remix recommends separating server-side logic into .server.js
files for security and performance reasons. When the hasServerCode
flag is set to true
, it means that server-side code like loaders, actions, and headers will be located in a .server.js
file, while client-side logic remains in the main component file.
To ensure that routes
understands there is a .server.js
file in addition to componentPath
, make sure to set hasServerCode
to true
.
Example Configuration When hasServerCode
is true
{
"/login": {
"hasLoader": true,
"hasServerCode": true,
"componentPath": "@adminide-stack/user-auth0-browser-ant/lib/components/Login/index.js"
}
}
Generated Wrapper When hasServerCode
is true
import OriginalComponent from '@adminide-stack/user-auth0-browser-ant/lib/components/Login/index.js';
import { loader as loaderFunc } from '@adminide-stack/user-auth0-browser-ant/lib/components/Login/index.server.js';
Example Configuration When hasServerCode
is false
{
"/login": {
"hasLoader": true,
"hasServerCode": false,
"componentPath": "@adminide-stack/user-auth0-browser-ant/lib/components/Login/index.js"
}
}
Generated Wrapper When hasServerCode
is false
import OriginalComponent, { loader as loaderFunc } from '@adminide-stack/user-auth0-browser-ant/lib/components/Login/index.js';
By separating the server-side code into .server.js
files, we ensure that sensitive server-side logic is not included in the client bundle, as recommended by Remix.
Client-Side Loaders
Client-side loaders are used to fetch data on the client after the initial render. They are configured using the hasClientLoader
field in routes.json
.
Syntax
{
"/path": {
"hasClientLoader": true
}
}
Implementation
When hasClientLoader
is set to true
, you need to implement a client loader function:
export const clientLoader = async ({ params }) => {
// Fetch data here
return { data };
};
Actions for Form Submissions and Mutations
Actions are used for handling form submissions and mutations. They are configured using the hasAction
field in routes.json
.
Syntax
{
"/path": {
"hasAction": true
}
}
Implementation
When hasAction
is set to true
, you need to implement an action function:
export const action = async ({ request }) => {
// Handle form submission or mutation here
return { result };
};
Integrating Loaders with Authentication and Authorization
Loaders can be integrated with authentication and authorization by checking the user's permissions before fetching data:
export const loader = async ({ params, context }) => {
const { user } = context;
if (!user) {
throw new Error('Unauthorized');
}
if (!user.hasPermission('required.permission')) {
throw new Error('Forbidden');
}
// Fetch data here
return { data };
};
Why Separating Server-Side Code Matters
Separating server-side code into .server.js
files provides the following benefits:
- Security: Sensitive logic is not included in the client bundle.
- Performance: Smaller client bundles and faster loading times.
- Clarity: Clear distinction between client and server code, improving maintainability.
Back to Index | Previous: Authentication | Next: Middleware System