Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion data/sidebar_react_latest.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
"styling",
"router",
"lazy-components",
"import-export-reactjs"
"import-export-reactjs",
"server-components"
],
"Hooks & State Management": [
"hooks-overview",
Expand Down
190 changes: 190 additions & 0 deletions pages/docs/react/latest/server-components.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
---
title: Server Components
description: "Creating React components"
canonical: "/docs/react/latest/server-components"
---

# Server Components

ReScript allows you to create server components as described in [React 19](https://react.dev/reference/rsc/server-components).

## Server Functions

To mark a file exposing functions as [Server Functions](https://react.dev/reference/rsc/server-functions),
you can use the `@@directive("'use server'")` tag.

<CodeTab labels={["ReScript", "JS Output"]}>

```res example
// src/actions/MyActions.res
@@directive("'use server'")

let myHelper = () => "Hello from the server!"

let helloWorld = async () => {
let response = myHelper()
response
}
```
```js
'use server'
// Generated by ReScript, PLEASE EDIT WITH CARE


function myHelper() {
return "Hello from the server!";
}

async function helloWorld() {
return "Hello from the server!";
}

export {
myHelper,
helloWorld,
}
```

</CodeTab>

**Warning:** It is recommended to use an interface file here, to ensure only the functions you want to expose are exposed.

```res
// src/actions/MyActions.resi
let helloWorld: unit => Promise<string>
```

`myHelper` will remain unexported with this change.

## Server Components

[Server components](https://react.dev/reference/rsc/server-components) can be async.

<CodeTab labels={["ReScript", "JS Output"]}>

```res example
// src/pages/Index.res
@react.component
let make = async () => {
let data = await getData()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would be cool if we could actually do something with data

<html>
<body>
<h1> {React.string("Hello from server component")} </h1>
</body>
</html>
}

// Export as default
let default = make
```
```js
'use server'
import * as JsxRuntime from "react/jsx-runtime";

async function make(param) {
await moo();
return JsxRuntime.jsx("html", {
children: JsxRuntime.jsx("body", {
children: JsxRuntime.jsx("h1", {
children: "Hello from server component"
})
})
});
}

let Index = make;

let make$1 = Index;

let $$default = Index;

export {
make$1 as make,
$$default as default,
}
```

</CodeTab>

A server function can be inlined in a server component and passed as prop to a client component.

<CodeTab labels={["ReScript", "JS Output"]}>

```res
@react.component
let make = async () => {
let data = await getData()

let addData =
@directive("'use server'")
async (name: string) => {
// add to data store
true
}
<html>
<body>
<h1> {React.string("Hello from server component")} </h1>
<ClientComp submit={addData} />
</body>
</html>
}
```
```js
async function make(param) {
await moo();
let addData = async name => {
'use server';
return true;
};
return JsxRuntime.jsx("html", {
children: JsxRuntime.jsxs("body", {
children: [
JsxRuntime.jsx("h1", {
children: "Hello from server component"
}),
JsxRuntime.jsx(ClientComp, {
submit: addData
})
]
})
});
}
```

</CodeTab>

**Note** that when decorating the function with `@directive("'use server'")`, we use a single `@`, where to annotate an entire file we use `@@directive("'use server'")`.

## Client Components

[Client components](https://react.dev/reference/rsc/use-client) should use the `@@directive("'use client'")` attribute.

<CodeTab labels={["ReScript", "JS Output"]}>

```res
// src/components/ClientComp.res
@@directive("'use client'")

@react.component
let make = (~submit) => <button> {React.string("yow from client")} </button>
```
```js
use client'
// Generated by ReScript, PLEASE EDIT WITH CARE

import * as JsxRuntime from "react/jsx-runtime";

function ClientComp(props) {
return JsxRuntime.jsx("button", {
children: "yow from client"
});
}

let make = ClientComp;

export {
make,
}
```

</CodeTab>
Loading