---
source_hash: "414b4da7"
title: "Routing"
weight: 160
---

# Routing

[React Router v7 Documentation](https://reactrouter.com/)

SmartMaker uses **React Router** to manage navigation between application pages (Single Page Application).

## Basic Configuration

### Create the Router

```javascript
// src/components/app/Router/index.jsx

import { BrowserRouter, Routes, Route } from 'react-router-dom';

import { LoginPage } from '../../pages/public/LoginPage';
import { HomePage } from '../../pages/private/HomePage';
import { Error404Page } from '../../pages/errors/Error404Page';

export const Router = () => {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/login" element={<LoginPage />} />
        <Route path="/" element={<HomePage />} />
        <Route path="*" element={<Error404Page />} />
      </Routes>
    </BrowserRouter>
  );
};
```

### Integrate into App.jsx

```javascript
// src/App.jsx

import { Provider } from '@cap-rel/smartcommon';
import { Router } from './components/app/Router';
import { config } from './appConfig';

export const App = () => {
  return (
    <Provider config={config}>
      <Router />
    </Provider>
  );
};
```

## Protected Routes

> [!TIP]
> **With smartcommon, use `<RouteGuard>`**: it covers 4 modes (`requireAuth`, `requireGuest`, `requireDeviceIdentification`, `requireDeviceIdentified`) and directly reads `useApi().user` / `user.deviceOptions`. See [Advanced Components -> RouteGuard](/front/composants-avances#routeguard) for the full version. The manual version below remains useful pedagogically or for business rules that do not fit these 4 modes.

### RouteGuard (Recommended)

```javascript
import { RouteGuard } from '@cap-rel/smartcommon';

<Routes>
  <Route element={<RouteGuard requireGuest />}>
    <Route path="/login" element={<LoginPage />} />
    <Route path="/welcome" element={<WelcomePage />} />
  </Route>

  <Route element={<RouteGuard requireDeviceIdentified />}>
    <Route path="/" element={<HomePage />} />
    <Route path="/settings" element={<SettingsPage />} />
  </Route>
</Routes>
```

### Authentication Guards (Manual)

```javascript
// src/components/app/Router/Guards/index.jsx

import { Outlet, Navigate } from 'react-router-dom';
import { useGlobalStates } from '@cap-rel/smartcommon';

/**
 * Public routes (login, register, etc.)
 * Redirects to / if already logged in
 */
export const PublicRoutes = () => {
  const gst = useGlobalStates();
  const session = gst.get('session');

  if (session) {
    return <Navigate to="/" replace />;
  }

  return <Outlet />;
};

/**
 * Private routes (home, settings, etc.)
 * Redirects to /login if not authenticated
 */
export const PrivateRoutes = () => {
  const gst = useGlobalStates();
  const session = gst.get('session');

  if (!session) {
    return <Navigate to="/login" replace />;
  }

  return <Outlet />;
};
```

### Using Guards

```javascript
// src/components/app/Router/index.jsx

import { BrowserRouter, Routes, Route } from 'react-router-dom';
import { PublicRoutes, PrivateRoutes } from './Guards';

// Public pages
import { WelcomePage } from '../../pages/public/WelcomePage';
import { LoginPage } from '../../pages/public/LoginPage';

// Private pages
import { HomePage } from '../../pages/private/HomePage';
import { SettingsPage } from '../../pages/private/SettingsPage';
import { ItemPage } from '../../pages/private/ItemPage';

// Errors
import { Error404Page } from '../../pages/errors/Error404Page';

export const Router = () => {
  return (
    <BrowserRouter>
      <Routes>
        {/* Public routes */}
        <Route element={<PublicRoutes />}>
          <Route path="/welcome" element={<WelcomePage />} />
          <Route path="/login" element={<LoginPage />} />
        </Route>

        {/* Private routes */}
        <Route element={<PrivateRoutes />}>
          <Route path="/" element={<HomePage />} />
          <Route path="/settings" element={<SettingsPage />} />
          <Route path="/items/:id" element={<ItemPage />} />
        </Route>

        {/* Fallback 404 */}
        <Route path="*" element={<Error404Page />} />
      </Routes>
    </BrowserRouter>
  );
};
```

## Navigation

### useNavigation Hook

SmartCommon exposes `useNavigation` which returns an object with navigation methods:

```javascript
import { useNavigation } from '@cap-rel/smartcommon';

const MyComponent = () => {
  const nav = useNavigation();

  return (
    <div>
      {/* Simple navigation */}
      <button onClick={() => nav.navigate('/')}>Home</button>
      <button onClick={() => nav.navigate('/settings')}>Settings</button>

      {/* With parameters */}
      <button onClick={() => nav.navigate(`/items/${itemId}`)}>View item</button>

      {/* Go back */}
      <button onClick={() => nav.navigate(-1)}>Back</button>

      {/* Replace history (chainable builder) */}
      <button onClick={() => nav.replace().to('/login')}>
        Logout
      </button>
    </div>
  );
};
```

### Returned Properties

| Property | Description |
| --- | --- |
| `nav.navigate(to, options)` | React Router navigation function |
| `nav.params` | Route parameters (useParams) |
| `nav.searchParams` | Query string (useSearchParams) |
| `nav.location` | Current location object |
| `nav.history` | Navigation history |
| `nav.replace()` | Chainable builder: replace instead of push |
| `nav.state(value)` | Chainable builder: pass a state |
| `nav.to(path)` | Chainable builder: execute navigation |

### Link Component

For simple links, use the `Link` component:

```javascript
import { Link } from 'react-router-dom';

const Navigation = () => {
  return (
    <nav>
      <Link to="/">Home</Link>
      <Link to="/settings">Settings</Link>
      <Link to="/items/123">Item 123</Link>
    </nav>
  );
};
```

## Route Parameters

### Dynamic Parameters

```javascript
// Route with parameter :id
<Route path="/items/:id" element={<ItemPage />} />

// Get the parameter
import { useParams } from 'react-router-dom';

const ItemPage = () => {
  const { id } = useParams();  // id = "123" for /items/123

  return <div>Item #{id}</div>;
};
```

### Multiple Parameters

```javascript
// Route with multiple parameters
<Route path="/users/:userId/posts/:postId" element={<PostPage />} />

const PostPage = () => {
  const { userId, postId } = useParams();
  // ...
};
```

### Query Strings

```javascript
import { useSearchParams } from 'react-router-dom';

const SearchPage = () => {
  const [searchParams, setSearchParams] = useSearchParams();

  // Read: /search?q=test&page=2
  const query = searchParams.get('q');     // "test"
  const page = searchParams.get('page');   // "2"

  // Modify
  const handleSearch = (newQuery) => {
    setSearchParams({ q: newQuery, page: '1' });
  };

  return (
    <input
      value={query || ''}
      onChange={(e) => handleSearch(e.target.value)}
    />
  );
};
```

## Nested Routes

### Shared Layout

```javascript
// src/components/app/Router/index.jsx

<Routes>
  <Route element={<PrivateRoutes />}>
    {/* Layout with bottom navigation */}
    <Route element={<MainLayout />}>
      <Route path="/" element={<HomePage />} />
      <Route path="/search" element={<SearchPage />} />
      <Route path="/profile" element={<ProfilePage />} />
    </Route>

    {/* Pages without bottom navigation */}
    <Route path="/items/:id" element={<ItemPage />} />
    <Route path="/settings" element={<SettingsPage />} />
  </Route>
</Routes>
```

### Layout Component

```javascript
// src/components/layouts/MainLayout/index.jsx

import { Outlet } from 'react-router-dom';
import { useNavigation } from '@cap-rel/smartcommon';

export const MainLayout = () => {
  const nav = useNavigation();

  return (
    <div className="min-h-screen flex flex-col">
      {/* Page content (Outlet = route child) */}
      <main className="flex-1">
        <Outlet />
      </main>

      {/* Fixed bottom navigation */}
      <nav className="bg-white shadow-lg p-2 flex justify-around">
        <button onClick={() => nav.navigate('/')}>Home</button>
        <button onClick={() => nav.navigate('/search')}>Search</button>
        <button onClick={() => nav.navigate('/profile')}>Profile</button>
      </nav>
    </div>
  );
};
```

## Transition Animations

### Configuration in appConfig

```javascript
// appConfig.js

export const config = {
  pages: {
    // From home
    "/": {
      "/settings": "slideLeft",   // Home -> Settings: slide left
      "/items/*": "slideLeft",    // Home -> Item: slide left
      "*": "fade",                // Others: fade
    },
    // From settings
    "/settings": {
      "/": "slideRight",          // Settings -> Home: slide right
    },
    // Default
    "*": "fade",
  },
};
```

### Available Animations

| Animation | Description |
| --- | --- |
| `fade` | Crossfade |
| `slideLeft` | Slide left |
| `slideRight` | Slide right |
| `zoom` | Zoom in/out |

See [Animations](/front/animations) for more details.

## Error Handling

### 404 Page

```javascript
// src/components/pages/errors/Error404Page/index.jsx

import { useNavigation } from '@cap-rel/smartcommon';

export const Error404Page = () => {
  const nav = useNavigation();

  return (
    <div className="min-h-screen flex flex-col items-center justify-center p-4">
      <h1 className="text-6xl font-bold text-gray-300 mb-4">404</h1>
      <p className="text-gray-600 mb-8">Page not found</p>
      <button
        onClick={() => nav.navigate('/')}
        className="bg-primary text-white px-6 py-3 rounded-lg"
      >
        Back to Home
      </button>
    </div>
  );
};
```

### Conditional Redirect

```javascript
import { Navigate, useLocation } from 'react-router-dom';
import { useGlobalStates } from '@cap-rel/smartcommon';

const RequireAuth = ({ children }) => {
  const gst = useGlobalStates();
  const session = gst.get('session');
  const location = useLocation();

  if (!session) {
    // Save URL to redirect after login
    return <Navigate to="/login" state={{ from: location }} replace />;
  }

  return children;
};
```

## Best Practices

### Route Structure
- Group routes by type (public, private, errors)
- Use guards for protection
- Place the `*` fallback last

### Navigation
- Prefer SmartCommon's `useNavigation`
- Use `replace: true` for redirects (login, logout)
- Avoid hardcoded paths, use constants

### Performance
- Lazy loading for large pages
- Light animations on mobile
- Preload critical data

## See Also
- [Animations](/front/animations) - Page Transitions
- [Components and Pages](/front/composants-et-pages) - Page Structure
- [Hooks](/front/hooks) - useNavigation
- [Configuration](/front/configuration) - Provider Options
