or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

deep-linking.mdindex.mdlink-components.mdnavigation-container.mdnavigation-hooks.mdserver-side-rendering.mdstatic-navigation.mdtheming.md

server-side-rendering.mddocs/

0

# Server-Side Rendering

1

2

React Navigation provides server-side rendering (SSR) support for web applications through the ServerContainer component and related utilities. This enables proper navigation state management during server rendering.

3

4

## Capabilities

5

6

### ServerContainer Component

7

8

Container component specifically designed for server-side rendering contexts.

9

10

```typescript { .api }

11

/**

12

* Container component for server rendering.

13

* Should only be used on the server with react-dom/server for SSR.

14

*/

15

function ServerContainer(

16

props: {

17

/** Location object to base the initial URL for SSR */

18

location: {

19

/** Current pathname */

20

pathname: string;

21

/** Query string */

22

search?: string;

23

/** Hash fragment */

24

hash?: string;

25

};

26

/** Child elements to render the content */

27

children: React.ReactNode;

28

} & React.RefAttributes<ServerContainerRef>

29

): React.ReactElement;

30

31

interface ServerContainerRef {

32

/** Get current navigation options during SSR */

33

getCurrentOptions(): Record<string, any> | undefined;

34

}

35

```

36

37

**Usage Examples:**

38

39

```typescript

40

import { ServerContainer } from '@react-navigation/native';

41

import { renderToString } from 'react-dom/server';

42

43

// Basic server-side rendering setup

44

function renderApp(req: Request) {

45

const location = {

46

pathname: req.url,

47

search: req.query ? `?${new URLSearchParams(req.query).toString()}` : '',

48

};

49

50

const html = renderToString(

51

<ServerContainer location={location}>

52

{/* Your navigation structure */}

53

<Stack.Navigator>

54

<Stack.Screen name="Home" component={HomeScreen} />

55

<Stack.Screen name="About" component={AboutScreen} />

56

</Stack.Navigator>

57

</ServerContainer>

58

);

59

60

return html;

61

}

62

63

// Express.js server setup

64

app.get('*', (req, res) => {

65

const location = {

66

pathname: req.path,

67

search: req.url.includes('?') ? req.url.split('?')[1] : '',

68

};

69

70

const appHtml = renderToString(

71

<ServerContainer location={location}>

72

<App />

73

</ServerContainer>

74

);

75

76

const html = `

77

<!DOCTYPE html>

78

<html>

79

<head>

80

<title>My App</title>

81

<meta charset="utf-8" />

82

</head>

83

<body>

84

<div id="root">${appHtml}</div>

85

<script src="/client.js"></script>

86

</body>

87

</html>

88

`;

89

90

res.send(html);

91

});

92

93

// Next.js integration

94

function MyApp({ Component, pageProps, router }) {

95

if (typeof window === 'undefined') {

96

// Server-side rendering

97

return (

98

<ServerContainer location={{ pathname: router.asPath }}>

99

<Component {...pageProps} />

100

</ServerContainer>

101

);

102

}

103

104

// Client-side rendering

105

return (

106

<NavigationContainer>

107

<Component {...pageProps} />

108

</NavigationContainer>

109

);

110

}

111

```

112

113

### Server Context

114

115

React context that provides server-side location information to child components.

116

117

```typescript { .api }

118

interface ServerContextType {

119

/** Location object for server rendering */

120

location: {

121

pathname: string;

122

search?: string;

123

hash?: string;

124

};

125

}

126

127

// Server context is automatically provided by ServerContainer

128

// Access it using React.useContext if needed for custom components

129

const ServerContext: React.Context<ServerContextType | undefined>;

130

```

131

132

**Context Usage Examples:**

133

134

```typescript

135

import { ServerContext } from '@react-navigation/native';

136

137

// Access server location in components

138

function ServerAwareComponent() {

139

const serverContext = useContext(ServerContext);

140

141

if (serverContext) {

142

// Running on server

143

const { pathname, search } = serverContext.location;

144

console.log('Server rendering path:', pathname + (search || ''));

145

}

146

147

return <Text>Server-aware content</Text>;

148

}

149

150

// Conditional rendering based on server context

151

function ConditionalServerComponent() {

152

const serverContext = useContext(ServerContext);

153

const isServer = serverContext !== undefined;

154

155

return (

156

<View>

157

{isServer ? (

158

<Text>Rendered on server</Text>

159

) : (

160

<Text>Rendered on client</Text>

161

)}

162

</View>

163

);

164

}

165

```

166

167

### SSR Navigation State

168

169

Handle navigation state during server-side rendering with proper hydration.

170

171

```typescript { .api }

172

// Server navigation state management

173

interface SSRNavigationState {

174

/** Initial state derived from server location */

175

initialState?: NavigationState;

176

/** Whether hydration should preserve server state */

177

preserveState?: boolean;

178

}

179

```

180

181

**State Management Examples:**

182

183

```typescript

184

// Server-side state extraction

185

function getInitialNavigationState(pathname: string): NavigationState | undefined {

186

// Parse pathname to determine initial navigation state

187

if (pathname === '/') {

188

return {

189

routes: [{ name: 'Home', key: 'home' }],

190

index: 0,

191

};

192

} else if (pathname.startsWith('/profile/')) {

193

const userId = pathname.split('/')[2];

194

return {

195

routes: [

196

{ name: 'Home', key: 'home' },

197

{ name: 'Profile', key: 'profile', params: { userId } },

198

],

199

index: 1,

200

};

201

}

202

203

return undefined;

204

}

205

206

// SSR with navigation state

207

function serverRender(req: Request) {

208

const location = { pathname: req.path };

209

const initialState = getInitialNavigationState(req.path);

210

211

const html = renderToString(

212

<ServerContainer location={location}>

213

<NavigationContainer initialState={initialState}>

214

<Stack.Navigator>

215

<Stack.Screen name="Home" component={HomeScreen} />

216

<Stack.Screen name="Profile" component={ProfileScreen} />

217

</Stack.Navigator>

218

</NavigationContainer>

219

</ServerContainer>

220

);

221

222

return html;

223

}

224

225

// Client-side hydration

226

function clientHydrate() {

227

const initialState = window.__INITIAL_NAVIGATION_STATE__;

228

229

hydrateRoot(

230

document.getElementById('root'),

231

<NavigationContainer initialState={initialState}>

232

<App />

233

</NavigationContainer>

234

);

235

}

236

```

237

238

### SEO and Meta Tags

239

240

Handle SEO metadata and document titles during server-side rendering.

241

242

```typescript { .api }

243

// SEO support through server container ref

244

interface SSRMetadata {

245

title?: string;

246

description?: string;

247

canonicalUrl?: string;

248

openGraph?: Record<string, string>;

249

}

250

```

251

252

**SEO Examples:**

253

254

```typescript

255

// Extract metadata during SSR

256

function renderWithMetadata(req: Request) {

257

const serverContainerRef = useRef<ServerContainerRef>(null);

258

const location = { pathname: req.path };

259

260

const html = renderToString(

261

<ServerContainer ref={serverContainerRef} location={location}>

262

<App />

263

</ServerContainer>

264

);

265

266

// Extract navigation options for metadata

267

const options = serverContainerRef.current?.getCurrentOptions();

268

const title = options?.title || 'Default Title';

269

const description = options?.description || 'Default description';

270

271

const fullHtml = `

272

<!DOCTYPE html>

273

<html>

274

<head>

275

<title>${title}</title>

276

<meta name="description" content="${description}" />

277

<meta property="og:title" content="${title}" />

278

<meta property="og:description" content="${description}" />

279

<link rel="canonical" href="${req.protocol}://${req.get('host')}${req.path}" />

280

</head>

281

<body>

282

<div id="root">${html}</div>

283

</body>

284

</html>

285

`;

286

287

return fullHtml;

288

}

289

290

// Screen with SEO metadata

291

function ProfileScreen({ route }) {

292

const { userId } = route.params;

293

294

useLayoutEffect(() => {

295

navigation.setOptions({

296

title: `Profile - ${userId}`,

297

description: `View profile information for user ${userId}`,

298

});

299

}, [userId]);

300

301

return <ProfileContent userId={userId} />;

302

}

303

```

304

305

### Error Handling

306

307

Handle errors gracefully during server-side rendering.

308

309

```typescript { .api }

310

// SSR error handling patterns

311

interface SSRErrorBoundary {

312

/** Fallback component for server errors */

313

fallback: React.ComponentType<{ error: Error }>;

314

/** Error logging during SSR */

315

onError?: (error: Error) => void;

316

}

317

```

318

319

**Error Handling Examples:**

320

321

```typescript

322

// Server error boundary

323

class SSRErrorBoundary extends React.Component {

324

constructor(props) {

325

super(props);

326

this.state = { hasError: false, error: null };

327

}

328

329

static getDerivedStateFromError(error) {

330

return { hasError: true, error };

331

}

332

333

componentDidCatch(error, errorInfo) {

334

// Log error during SSR

335

console.error('SSR Navigation Error:', error, errorInfo);

336

}

337

338

render() {

339

if (this.state.hasError) {

340

return (

341

<div>

342

<h1>Navigation Error</h1>

343

<p>Unable to render navigation on server</p>

344

</div>

345

);

346

}

347

348

return this.props.children;

349

}

350

}

351

352

// Safe SSR rendering

353

function safeServerRender(req: Request) {

354

try {

355

const location = { pathname: req.path };

356

357

const html = renderToString(

358

<SSRErrorBoundary>

359

<ServerContainer location={location}>

360

<App />

361

</ServerContainer>

362

</SSRErrorBoundary>

363

);

364

365

return html;

366

} catch (error) {

367

console.error('Server rendering failed:', error);

368

369

// Return minimal HTML fallback

370

return `

371

<div id="root">

372

<div>Loading...</div>

373

<script>

374

// Client will take over

375

window.__SSR_ERROR__ = true;

376

</script>

377

</div>

378

`;

379

}

380

}

381

382

// Client-side fallback handling

383

function clientWithFallback() {

384

const hasSSRError = window.__SSR_ERROR__;

385

386

if (hasSSRError) {

387

// Full client-side rendering

388

render(

389

<NavigationContainer>

390

<App />

391

</NavigationContainer>,

392

document.getElementById('root')

393

);

394

} else {

395

// Normal hydration

396

hydrateRoot(

397

document.getElementById('root'),

398

<NavigationContainer>

399

<App />

400

</NavigationContainer>

401

);

402

}

403

}

404

```

405

406

### Platform Detection

407

408

Properly detect and handle server-side rendering context.

409

410

```typescript { .api }

411

// Platform detection utilities

412

interface PlatformDetection {

413

isServer: boolean;

414

isClient: boolean;

415

canUseDOM: boolean;

416

}

417

```

418

419

**Platform Detection Examples:**

420

421

```typescript

422

// Universal platform detection

423

const isServer = typeof window === 'undefined';

424

const isClient = typeof window !== 'undefined';

425

426

// Navigation container selection

427

function UniversalNavigationContainer({ children, ...props }) {

428

if (isServer) {

429

return (

430

<ServerContainer {...props}>

431

{children}

432

</ServerContainer>

433

);

434

}

435

436

return (

437

<NavigationContainer {...props}>

438

{children}

439

</NavigationContainer>

440

);

441

}

442

443

// Feature detection during SSR

444

function FeatureAwareComponent() {

445

const [canUseFeature, setCanUseFeature] = useState(false);

446

447

useEffect(() => {

448

// Only run on client

449

if (typeof window !== 'undefined') {

450

setCanUseFeature(true);

451

}

452

}, []);

453

454

return (

455

<View>

456

{canUseFeature ? (

457

<ClientOnlyFeature />

458

) : (

459

<ServerSafeContent />

460

)}

461

</View>

462

);

463

}

464

```