Request Context
The RequestContext
is a set of utilities provided by Brisa to facilitate the development of server components. It is a Request
with some extra functionalities such as managing store, handling context, i18n, and more.
import type { RequestContext } from "brisa";
export default function ServerComponent(props, requestContext: RequestContext) {
const {
// Shared data across server/web components
store,
useContext,
// Useful to control pending state in server components
indicate,
// Data of the current route
route,
// Consume translations and control internationalization
i18n,
// Access to websockets
ws,
// Get the user IP
getIp,
// The `finalURL` is the path of your page file
finalURL,
// Request id
id,
// The initiator of the request ("SERVER_ACTION", "SPA_NAVIGATION", "INITIAL_REQUEST", "API_REQUEST")
initiator,
// Add styles
css,
} = requestContext;
// ... Server component implementation ...
}
Being an extension of the Request, you also have access to all fields of the Request.
In contrast to other frameworks that necessitate imports, our methodology incorporates all these properties directly within each server component.
store
The store
property is an extended map where values can be stored and shared among all web components. It serves as a global state accessible by all components. Values can be set and retrieved using the store.set
and store.get
methods.
Example setting a value:
store.set("count", 0);
Example getting a value:
<div>{store.get("count")}</div>
The server
store
only lives at request time so that any server component can access the store unless you usetransferToClient
, which extends the life of the store.
transferToClient
The store
data from request context is only available on the server. So you can store sensitive data without worrying. However, you can transfer certain data to the client side (web-components) using store.transferToClient
method.
import { type RequestContext } from "brisa";
export default async function SomeComponent({}, request: RequestContext) {
const data = await getData(request);
request.store.set("data", data);
// Transfer "data" from store to client
request.store.transferToClient(["data"]);
// ..
}
This allows access to these values from the web component store.
This setup also enables subsequent server actions to access the same store
, as the communication flows through the client:
server render
โ client
โ server action
โ client
It is a way to modify in a reactive way from a server action the web components that consume this store
.
You can encrypt store data if you want to transfer sensitive data to the server actions so that it cannot be accessed from the client.
useContext
useContext: <T>(context: BrisaContext<T>) => { value: T }
The useContext
method is used to consume a context value. It takes a BrisaContext
as a parameter and returns a signal containing the context value. The context value is often used for passing data between a provider and multiple consumers within a component tree.
Example:
const foo = useContext(context);
return <div>{foo.value}</div>;
For more details, refer to the context documentation.
When referring to
useContext
, it is essential to note that this term should not be confused with the broader concept ofRequestContext
mentioned earlier. TheuseContext
is a Brisa Hook for consuming context value, that is piece of data that can be shared across multiple Brisa components. TheRequestContext
denotes the overall environment and configuration specific to each server component, offering a unique and more comprehensive control mechanism. Understanding this distinction is crucial for a clear comprehension of our framework's architecture.
indicate
indicate(actionName: string): IndicatorSignal
The indicate
method is used to add it in the indicator
HTML extended attribute. This indicator
automatically set the brisa-request
class while the indicated server action is pending.
const pending = indicate('some-server-action-name');
// ...
css`
span { display: none }
span.brisa-request { display: inline }
`
// ...
<>
<button onClick={someAction} indicateClick={pending}>
Run some action
</button>
<span indicator={pending}>Pending...</span>
</>
Parameters:
string
- Indicator name. It can refer to the server action. The idea is that you can use the same indicator in other components (both server and web) using the same name to relate it to the same server action.
For more details, take a look to:
indicate
in web components, similar method but fromWebContext
.indicate[Event]
HTML extended attribute to use it in server components to register the server action indicator.indicator
HTML extended attribute to use it in any element of server/web components.
route
The route is the matched route of the request.
You can access to:
params
- for dynamic routes like/[user]
you can access toparams.user
.filePath
- path of your page file.pathname
- path portion of the URL.query
- A record of query parameters extracted from the URL.name
- The name associated with the route.kind
- The type of route:exact
,catch-all
,optional-catch-all
, ordynamic
.src
- The source string representing the route.
Example of object:
{
filePath: "/Users/aralroca/Documents/brisa/fun/pages/blog/[slug].tsx",
kind: "dynamic",
name: "/blog/[slug]",
pathname: "/blog/my-cool-post",
src: "/blog/[slug].js",
params: {
slug: "my-cool-post"
}
}
Example consuming:
<div>{route.pathname}</div>
i18n
i18n: I18n
The i18n
object provides utilities for accessing the locale and consuming translations within components.
Example:
const { t, locale } = i18n;
return <div>{t("hello-world")}</div>;
For more details, refer to the i18n documentation.
ws
In case you have configured WebSockets, you can access them from any server component, api route, middleware, etc. The ws
is of type ServerWebSocket
, where is:
interface ServerWebSocket {
readonly data: any;
readonly readyState: number;
readonly remoteAddress: string;
send(message: string | ArrayBuffer | Uint8Array, compress?: boolean): number;
close(code?: number, reason?: string): void;
subscribe(topic: string): void;
unsubscribe(topic: string): void;
publish(topic: string, message: string | ArrayBuffer | Uint8Array): void;
isSubscribed(topic: string): boolean;
cork(cb: (ws: ServerWebSocket) => void): void;
}
Example:
import { type RequestContext } from "brisa";
export function GET({ ws, i18n }: RequestContext) {
const message = i18n.t("hello-world");
// Sending a WebSocket message from an API route
ws.send(message);
return new Response(message, {
headers: { "content-type": "text/plain" },
});
}
For more information see Bun's WebSockets documentation.
getIP
The IP address of a given Request can be retrieved via getIP
.
Below it calls Bun's server.requestIP
.
finalURL
The finalURL
is the URL of your page, regardless of the fact that for the users it is another one.
Example, an user enter to:
/es/sobre-nosotros/
But the finalURL
is:
/about-us
Because your page is in src/pages/about-us/index.tsx
id
The id
is the unique identifier of the request. This id is used internally by Brisa, but we expose it to you because it can be useful for tracking.
Example:
console.log(id); // 1edfa3c2-e101-40e3-af57-8890795dacd4
initiator
The initiator
is a string that represents the initiator of the render. It can be:
Initiator.SERVER_ACTION
- When is the rerender by a server action.Initiator.SPA_NAVIGATION
- When the render is initiated by a SPA navigation.Initiator.INITIAL_REQUEST
- When the render is initiated by the initial request.Initiator.API_REQUEST
- When the render is initiated by an API request.
The default value is Initiator.INITIAL_REQUEST
.
This is useful to know how the render was initiated and to make decisions based on it, for example initializing the store only in the
Initiator.INITIAL_REQUEST
. For API routes, theinitiator
is alwaysInitiator.INITIAL_REQUEST
.
Example:
import { Initiator } from "brisa/server";
export default function ServerComponent(props, requestContext) {
if (requestContext.initiator === Initiator.INITIAL_REQUEST) {
requestContext.store.set("count", 0);
}
return <div>{requestContext.store.get("count")}</div>;
}
css
css(strings: TemplateStringsArray, ...values: string[]): void
The css
template literal is used to inject CSS into the DOM. It allows developers to define styles directly within server components using a template literal.
Unlike web components, this css
template literal in server components does not encapsulate. This code would affect all div
s on the page:
Example:
css`
div {
background-color: ${color};
}
`;
We recommend using the
css
template literal for specific cases such as generating CSS animations based on dynamic JavaScript variables.
For more details, refer to the Template literal css
documentation.