Skip to content

Commit 5de8a34

Browse files
committed
Add support for overridable Link component (e.g. ReactRouter/next.js)
1 parent dad2495 commit 5de8a34

26 files changed

+11055
-11298
lines changed

README.md

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,51 @@
11
# @servicestack/react
22

3-
This is ServiceStack's React Component Library.
3+
ServiceStack's React Component Library - A comprehensive collection of React components for building modern web applications.
4+
5+
## Features
6+
7+
- 🎨 **Beautiful UI Components** - Pre-styled components with Tailwind CSS
8+
- 🔄 **Framework Agnostic Routing** - Works with React Router, Next.js, or plain HTML
9+
-**React 19 Compatible** - Full support for React 19 including SSR mode
10+
- 📦 **TypeScript Support** - Fully typed components and APIs
11+
- 🎯 **AutoQuery Integration** - Built-in components for ServiceStack AutoQuery APIs
12+
- 🌙 **Dark Mode Support** - All components support dark mode out of the box
13+
14+
## Quick Start
15+
16+
### Installation
17+
18+
```bash
19+
npm install @servicestack/react
20+
```
21+
22+
### Configuration
23+
24+
The library supports multiple routing solutions. Choose the one that fits your project:
25+
26+
#### React Router (Vite, CRA, etc.)
27+
28+
```tsx
29+
import { setLinkComponent } from '@servicestack/react'
30+
import { Link } from 'react-router-dom'
31+
32+
setLinkComponent(Link)
33+
```
34+
35+
#### Next.js
36+
37+
```tsx
38+
import { setLinkComponent } from '@servicestack/react'
39+
import Link from 'next/link'
40+
41+
setLinkComponent(Link)
42+
```
43+
44+
#### No Router (Plain HTML)
45+
46+
No configuration needed! Components will automatically use standard anchor tags.
47+
48+
For detailed setup instructions, see [SETUP.md](./SETUP.md).
449

550
## Recommended IDE Setup
651

@@ -31,3 +76,20 @@ npm run dev
3176
```sh
3277
npm run build
3378
```
79+
80+
## Examples
81+
82+
Check out the [examples](./examples) directory for complete setup examples:
83+
84+
- [React Router Setup](./examples/react-router-setup.tsx) - Vite + React + React Router
85+
- [Next.js App Router Setup](./examples/nextjs-app-router-setup.tsx) - Next.js 13+ with App Router
86+
- [Next.js Pages Router Setup](./examples/nextjs-pages-router-setup.tsx) - Traditional Next.js routing
87+
- [No Router Setup](./examples/no-router-setup.tsx) - Plain React without routing
88+
89+
## Documentation
90+
91+
For comprehensive documentation, visit [docs.servicestack.net/react](https://docs.servicestack.net/react/)
92+
93+
## License
94+
95+
This project is licensed under the terms specified in the LICENSE file.

SETUP.md

Lines changed: 299 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,299 @@
1+
# @servicestack/react Setup Guide
2+
3+
This guide explains how to configure `@servicestack/react` for different React frameworks and routing solutions.
4+
5+
## Overview
6+
7+
The `@servicestack/react` component library is designed to work with multiple React frameworks and routing solutions:
8+
9+
- **Vite + React + React Router** - Client-side routing with react-router-dom
10+
- **Next.js** - Server-side rendering with Next.js App Router or Pages Router
11+
- **Plain React** - No routing library (uses standard anchor tags)
12+
13+
### Smart URL Handling
14+
15+
The library automatically detects and handles different types of URLs:
16+
17+
- **External URLs** (http://, https://, mailto:, tel:) - Always use plain `<a>` tags
18+
- **Internal URLs** (/path, /about, etc.) - Use configured Link component or fallback to `<a>` tags
19+
20+
This means you can use the same components for both internal navigation and external links without any special configuration!
21+
22+
## Installation
23+
24+
```bash
25+
npm install @servicestack/react
26+
```
27+
28+
### Optional Dependencies
29+
30+
Depending on your routing solution, you may need to install:
31+
32+
```bash
33+
# For React Router
34+
npm install react-router-dom
35+
36+
# For Next.js (already included in Next.js projects)
37+
# No additional installation needed
38+
```
39+
40+
## Configuration
41+
42+
### React Router (Vite, Create React App, etc.)
43+
44+
If you're using React Router, configure the library to use the `Link` component from `react-router-dom`:
45+
46+
```tsx
47+
import { setLinkComponent } from '@servicestack/react'
48+
import { Link } from 'react-router-dom'
49+
50+
// Configure the library to use React Router's Link
51+
setLinkComponent(Link)
52+
```
53+
54+
**Complete Example:**
55+
56+
```tsx
57+
// main.tsx or index.tsx
58+
import React from 'react'
59+
import ReactDOM from 'react-dom/client'
60+
import { BrowserRouter } from 'react-router-dom'
61+
import { setLinkComponent } from '@servicestack/react'
62+
import { Link } from 'react-router-dom'
63+
import App from './App'
64+
65+
// Configure routing
66+
setLinkComponent(Link)
67+
68+
ReactDOM.createRoot(document.getElementById('root')!).render(
69+
<React.StrictMode>
70+
<BrowserRouter>
71+
<App />
72+
</BrowserRouter>
73+
</React.StrictMode>
74+
)
75+
```
76+
77+
### Next.js
78+
79+
For Next.js applications, configure the library to use Next.js's `Link` component:
80+
81+
```tsx
82+
import { setLinkComponent } from '@servicestack/react'
83+
import Link from 'next/link'
84+
85+
// Configure the library to use Next.js Link
86+
setLinkComponent(Link)
87+
```
88+
89+
**App Router Example (app/layout.tsx):**
90+
91+
```tsx
92+
'use client'
93+
94+
import { setLinkComponent } from '@servicestack/react'
95+
import Link from 'next/link'
96+
import { useEffect } from 'react'
97+
98+
export default function RootLayout({
99+
children,
100+
}: {
101+
children: React.ReactNode
102+
}) {
103+
useEffect(() => {
104+
// Configure routing on client side
105+
setLinkComponent(Link)
106+
}, [])
107+
108+
return (
109+
<html lang="en">
110+
<body>{children}</body>
111+
</html>
112+
)
113+
}
114+
```
115+
116+
**Pages Router Example (_app.tsx):**
117+
118+
```tsx
119+
import type { AppProps } from 'next/app'
120+
import { setLinkComponent } from '@servicestack/react'
121+
import Link from 'next/link'
122+
import { useEffect } from 'react'
123+
124+
export default function App({ Component, pageProps }: AppProps) {
125+
useEffect(() => {
126+
// Configure routing
127+
setLinkComponent(Link)
128+
}, [])
129+
130+
return <Component {...pageProps} />
131+
}
132+
```
133+
134+
### Plain React (No Router)
135+
136+
If you're not using a routing library, the components will automatically fall back to using standard HTML anchor tags (`<a>`). No configuration is needed:
137+
138+
```tsx
139+
import { PrimaryButton } from '@servicestack/react'
140+
141+
// This will render as: <a href="/about"><button>...</button></a>
142+
<PrimaryButton href="/about">About</PrimaryButton>
143+
```
144+
145+
## Usage
146+
147+
Once configured, all navigation components will use your chosen routing solution:
148+
149+
### Button Components with Links
150+
151+
```tsx
152+
import { PrimaryButton, SecondaryButton, OutlineButton } from '@servicestack/react'
153+
154+
function MyComponent() {
155+
return (
156+
<div>
157+
{/* These will use your configured Link component */}
158+
<PrimaryButton href="/dashboard">Dashboard</PrimaryButton>
159+
<SecondaryButton href="/settings">Settings</SecondaryButton>
160+
<OutlineButton href="/profile">Profile</OutlineButton>
161+
</div>
162+
)
163+
}
164+
```
165+
166+
### Navigation Components
167+
168+
```tsx
169+
import { Breadcrumbs, Breadcrumb, NavList, NavListItem } from '@servicestack/react'
170+
171+
function Navigation() {
172+
return (
173+
<>
174+
<Breadcrumbs homeHref="/">
175+
<Breadcrumb href="/products">Products</Breadcrumb>
176+
<Breadcrumb>Details</Breadcrumb>
177+
</Breadcrumbs>
178+
179+
<NavList title="Main Navigation">
180+
<NavListItem
181+
title="Dashboard"
182+
href="/dashboard"
183+
iconSvg="..."
184+
>
185+
View your dashboard
186+
</NavListItem>
187+
</NavList>
188+
</>
189+
)
190+
}
191+
```
192+
193+
### External URLs
194+
195+
External URLs are automatically detected and use plain anchor tags (no routing):
196+
197+
```tsx
198+
import { PrimaryButton, TextLink } from '@servicestack/react'
199+
200+
function ExternalLinks() {
201+
return (
202+
<div>
203+
{/* External URLs - use plain <a> tags */}
204+
<PrimaryButton href="https://docs.servicestack.net">
205+
Documentation
206+
</PrimaryButton>
207+
208+
<TextLink href="mailto:support@example.com">
209+
Email Support
210+
</TextLink>
211+
212+
<SecondaryButton href="tel:+1234567890">
213+
Call Us
214+
</SecondaryButton>
215+
216+
{/* Internal URLs - use configured Link component */}
217+
<PrimaryButton href="/dashboard">
218+
Dashboard
219+
</PrimaryButton>
220+
</div>
221+
)
222+
}
223+
```
224+
225+
## React 19 SSR Compatibility
226+
227+
The library is fully compatible with React 19 in SSR mode. By making `react-router-dom` an optional peer dependency and providing a configurable Link component system, you can:
228+
229+
1. Use the library in Next.js with React 19 SSR
230+
2. Use the library in Vite + React Router without SSR issues
231+
3. Use the library without any routing library
232+
233+
## Troubleshooting
234+
235+
### "Link is not defined" errors
236+
237+
Make sure you've called `setLinkComponent()` before rendering any components that use navigation:
238+
239+
```tsx
240+
import { setLinkComponent } from '@servicestack/react'
241+
import { Link } from 'react-router-dom' // or from 'next/link'
242+
243+
setLinkComponent(Link)
244+
```
245+
246+
### Next.js: "Cannot read properties of undefined"
247+
248+
In Next.js, make sure to configure the Link component on the client side using `useEffect`:
249+
250+
```tsx
251+
'use client' // Add this for App Router
252+
253+
useEffect(() => {
254+
setLinkComponent(Link)
255+
}, [])
256+
```
257+
258+
### Links not working in Next.js
259+
260+
Next.js Link component has a different API. The library automatically detects and handles this, but make sure you're using a recent version of Next.js (13+).
261+
262+
## Advanced Configuration
263+
264+
You can also configure other aspects of the library:
265+
266+
```tsx
267+
import { setConfig } from '@servicestack/react'
268+
269+
setConfig({
270+
// Custom navigation function
271+
navigate: (url) => {
272+
// Custom navigation logic
273+
window.location.href = url
274+
},
275+
276+
// Asset path resolver
277+
assetsPathResolver: (src) => {
278+
return `https://cdn.example.com${src}`
279+
},
280+
281+
// And more...
282+
})
283+
```
284+
285+
## Migration from Previous Versions
286+
287+
If you're upgrading from a version that had a hard dependency on `react-router-dom`:
288+
289+
1. Install the library: `npm install @servicestack/react@latest`
290+
2. Add the Link configuration as shown above
291+
3. If using React Router, ensure `react-router-dom` is installed
292+
4. Test your navigation components
293+
294+
## Support
295+
296+
For issues, questions, or contributions, visit:
297+
- GitHub: https://github.com/ServiceStack/servicestack-react
298+
- Documentation: https://docs.servicestack.net/react/
299+

0 commit comments

Comments
 (0)