or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

client-apis.mddata-communication.mdindex.mdnodejs-integration.mdserver-apis.mdstatic-rendering.mdwebpack-plugin.md

data-communication.mddocs/

0

# Data Communication

1

2

Functions for encoding client-to-server data, decoding server responses, and handling form actions in React Server Components applications.

3

4

## Capabilities

5

6

### Encode Reply

7

8

Encodes client-side data for transmission to the server, supporting complex data structures, files, and temporary references.

9

10

```javascript { .api }

11

/**

12

* Encodes client data for server transmission

13

* @param value - Any serializable value to encode

14

* @param options - Optional encoding configuration

15

* @returns Promise resolving to encoded data in appropriate format

16

*/

17

function encodeReply(

18

value: ReactServerValue,

19

options?: EncodeReplyOptions

20

): Promise<string | URLSearchParams | FormData>;

21

```

22

23

**Usage Examples:**

24

25

```javascript

26

import { encodeReply } from "react-server-dom-webpack/client.browser";

27

28

// Encode simple data

29

const simpleData = await encodeReply({

30

action: "updateProfile",

31

userId: 123,

32

name: "John Doe"

33

});

34

35

// Encode with files

36

const formData = await encodeReply({

37

message: "Hello server",

38

files: [fileInput.files[0], fileInput.files[1]],

39

metadata: { timestamp: Date.now() }

40

});

41

42

// Encode with abort signal

43

const abortController = new AbortController();

44

const encodedData = await encodeReply(complexObject, {

45

signal: abortController.signal

46

});

47

48

// Send to server

49

await fetch("/api/server-action", {

50

method: "POST",

51

body: encodedData

52

});

53

```

54

55

### Decode Reply

56

57

Decodes client-transmitted data on the server side, handling various formats including FormData and JSON strings.

58

59

```javascript { .api }

60

/**

61

* Decodes client data sent to the server

62

* @param body - Request body containing encoded client data

63

* @param webpackMap - Optional server manifest for module resolution

64

* @param options - Optional configuration with temporary references

65

* @returns Promise resolving to decoded client data

66

*/

67

function decodeReply<T>(

68

body: string | FormData,

69

webpackMap?: ServerManifest,

70

options?: {temporaryReferences?: TemporaryReferenceSet}

71

): Thenable<T>;

72

```

73

74

**Usage Examples:**

75

76

```javascript

77

import { decodeReply } from "react-server-dom-webpack/server.node";

78

79

// Handle POST request with encoded data

80

export async function POST(request) {

81

const serverManifest = await loadServerManifest();

82

83

// Decode string body

84

const stringData = decodeReply(

85

await request.text(),

86

serverManifest

87

);

88

89

// Or decode FormData body

90

const formData = decodeReply(

91

await request.formData(),

92

serverManifest

93

);

94

95

// Process decoded data

96

const result = await processAction(formData);

97

return Response.json(result);

98

}

99

100

// Handle multipart uploads

101

async function handleUpload(request) {

102

const formData = await request.formData();

103

const decodedData = decodeReply(formData, serverManifest);

104

105

// Access files and regular data

106

const { files, userInput, metadata } = decodedData;

107

108

return processUpload(files, userInput, metadata);

109

}

110

```

111

112

### Decode Reply from Busboy

113

114

Specialized decoding for multipart form data using the busboy library, ideal for file uploads in Node.js environments.

115

116

```javascript { .api }

117

/**

118

* Decodes multipart form data using busboy for Node.js

119

* @param busboyStream - Busboy stream processing multipart data

120

* @param bundlerConfig - Optional server manifest for module resolution

121

* @returns Promise resolving to decoded form data with files and fields

122

*/

123

function decodeReplyFromBusboy(

124

busboyStream: any,

125

bundlerConfig?: ServerManifest

126

): Promise<any>;

127

```

128

129

**Usage Examples:**

130

131

```javascript

132

import { decodeReplyFromBusboy } from "react-server-dom-webpack/server.node";

133

import busboy from "busboy";

134

import { IncomingMessage } from "http";

135

136

// Handle file upload with busboy

137

async function handleFileUpload(req: IncomingMessage) {

138

const bb = busboy({

139

headers: req.headers,

140

limits: { fileSize: 10 * 1024 * 1024 } // 10MB limit

141

});

142

143

const decodedData = await decodeReplyFromBusboy(bb, serverManifest);

144

145

// Process uploaded files and form fields

146

const { files, fields } = decodedData;

147

148

for (const file of files) {

149

console.log(`Uploaded: ${file.filename}, Size: ${file.size}`);

150

await saveFile(file);

151

}

152

153

return { success: true, uploadedFiles: files.length };

154

}

155

156

// Express.js integration

157

app.post("/upload", async (req, res) => {

158

try {

159

const result = await handleFileUpload(req);

160

res.json(result);

161

} catch (error) {

162

res.status(500).json({ error: error.message });

163

}

164

});

165

```

166

167

### Decode Action

168

169

Decodes form actions submitted from client components, returning executable server functions.

170

171

```javascript { .api }

172

/**

173

* Decodes form action from client form submission

174

* @param body - FormData containing action information and arguments

175

* @param bundlerConfig - Optional server manifest for action resolution

176

* @returns Promise resolving to executable action function or null

177

*/

178

function decodeAction(

179

body: FormData,

180

bundlerConfig?: ServerManifest

181

): Promise<() => any> | null;

182

```

183

184

**Usage Examples:**

185

186

```javascript

187

import { decodeAction } from "react-server-dom-webpack/server.browser";

188

189

// Handle form action submission

190

export async function POST(request) {

191

const formData = await request.formData();

192

const action = await decodeAction(formData, serverManifest);

193

194

if (!action) {

195

return new Response("Invalid action", { status: 400 });

196

}

197

198

try {

199

// Execute the decoded action

200

const result = await action();

201

return Response.json(result);

202

} catch (error) {

203

return new Response(error.message, { status: 500 });

204

}

205

}

206

207

// Progressive enhancement form handling

208

async function handleFormSubmission(request) {

209

const formData = await request.formData();

210

211

// Try to decode as action first

212

const action = await decodeAction(formData, serverManifest);

213

214

if (action) {

215

// Handle as server action

216

return await action();

217

} else {

218

// Handle as traditional form submission

219

return handleTraditionalForm(formData);

220

}

221

}

222

```

223

224

### Decode Form State

225

226

Decodes form state information for progressive enhancement and form validation scenarios.

227

228

```javascript { .api }

229

/**

230

* Decodes form state from action result and form data

231

* @param actionResult - Result from previous action execution

232

* @param body - FormData containing current form state

233

* @param bundlerConfig - Optional server manifest for state resolution

234

* @returns Decoded form state for progressive enhancement

235

*/

236

function decodeFormState(

237

actionResult: any,

238

body: FormData,

239

bundlerConfig?: ServerManifest

240

): any;

241

```

242

243

**Usage Examples:**

244

245

```javascript

246

import { decodeFormState } from "react-server-dom-webpack/server.browser";

247

248

// Handle form with validation state

249

export async function handleFormWithState(request, previousResult) {

250

const formData = await request.formData();

251

252

const formState = decodeFormState(

253

previousResult,

254

formData,

255

serverManifest

256

);

257

258

// Use form state for validation and user feedback

259

if (formState.errors) {

260

return renderFormWithErrors(formState);

261

}

262

263

// Process valid form

264

return processValidForm(formState.data);

265

}

266

267

// Multi-step form handling

268

async function handleMultiStepForm(request, stepResult) {

269

const formData = await request.formData();

270

const currentState = decodeFormState(stepResult, formData, serverManifest);

271

272

if (currentState.isComplete) {

273

return processCompleteForm(currentState);

274

} else {

275

return renderNextStep(currentState);

276

}

277

}

278

```

279

280

### Data Serialization Patterns

281

282

Common patterns for handling complex data structures in client-server communication.

283

284

**Complex Object Encoding:**

285

286

```javascript

287

// Client-side: Encode complex nested object

288

const complexData = {

289

user: { id: 1, name: "Alice" },

290

preferences: { theme: "dark", notifications: true },

291

files: [file1, file2],

292

metadata: {

293

timestamp: new Date(),

294

location: navigator.geolocation

295

}

296

};

297

298

const encoded = await encodeReply(complexData);

299

300

// Server-side: Decode and access nested data

301

const decoded = decodeReply(await request.formData(), serverManifest);

302

console.log(decoded.user.name); // "Alice"

303

console.log(decoded.files.length); // 2

304

```

305

306

**File Upload Handling:**

307

308

```javascript

309

// Client-side: Encode files with metadata

310

const fileData = {

311

action: "uploadDocument",

312

files: Array.from(fileInput.files),

313

category: "documents",

314

tags: ["important", "project-a"]

315

};

316

317

const formData = await encodeReply(fileData);

318

319

// Server-side: Process uploaded files

320

const { action, files, category, tags } = decodeReply(formData, serverManifest);

321

322

for (const file of files) {

323

await saveFileWithMetadata(file, { category, tags });

324

}

325

```

326

327

## Types

328

329

```javascript { .api }

330

interface EncodeReplyOptions {

331

/** Set for tracking temporary references during encoding */

332

temporaryReferences?: TemporaryReferenceSet;

333

/** AbortSignal for cancelling encoding operation */

334

signal?: AbortSignal;

335

}

336

337

type ReactServerValue =

338

| string

339

| number

340

| boolean

341

| null

342

| undefined

343

| Array<ReactServerValue>

344

| { [key: string]: ReactServerValue }

345

| File

346

| Blob

347

| FormData

348

| URLSearchParams;

349

350

type ServerManifest = Record<string, any>;

351

type TemporaryReferenceSet = any;

352

353

interface DecodedFormData {

354

/** Uploaded files from multipart form */

355

files?: File[];

356

/** Form field values */

357

fields?: Record<string, string | string[]>;

358

/** Any additional encoded data */

359

[key: string]: any;

360

}

361

```