> ## Documentation Index
> Fetch the complete documentation index at: https://docs.scute.io/llms.txt
> Use this file to discover all available pages before exploring further.

# React Router (Declarative)

> Using Scute with React Router for declarative routing

For applications that need declarative routing with protected routes, you can combine Scute's React hooks with React Router. This approach provides a clean separation of concerns where each authentication step is handled as a separate route, and protected routes automatically redirect unauthenticated users.

Head over to the [example projects repo](https://github.com/scuteai/js/tree/main/examples) to see the React Router implementation in action and check out the [type docs](https://scute-js-docs.netlify.app/) for more `scuteClient` methods.

To get started, install our React SDK and React Router with your favorite package manager:

```sh title="Terminal" theme={null}
npm install @scute/react-hooks react-router
```

Add your credentials to your environment variable handler:

```sh theme={null}
VITE_SCUTE_APP_ID="YOUR_SCUTE_PROJECT_ID"
VITE_SCUTE_BASE_URL="YOUR_SCUTE_BASE_URL"
```

**NOTE**: If you are not using Vite, use "REACT\_APP" as your prefix for your environment variables.

### Initialize the Scute client

First initialize the Scute client using the `createClient` method exposed by `@scute/react-hooks` package:

```jsx theme={null}
// providers.jsx

import { createClient, AuthContextProvider } from "@scute/react-hooks";

const scuteClient = createClient({
    appId: import.meta.env.VITE_SCUTE_APP_ID,
    baseUrl: import.meta.env.VITE_SCUTE_BASE_URL,
  });

export default function Providers({ children }) {

  return (
    <AuthContextProvider scuteClient={scuteClient}>
      {children}
    </AuthContextProvider>
  );
}
```

### Wrap your React app with providers and router

Set up your app with both the Scute provider and React Router:

```jsx theme={null}
// main.jsx

import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { BrowserRouter } from "react-router-dom";
import App from "./App.jsx";
import Providers from "./providers.jsx";

createRoot(document.getElementById("root")).render(
  <StrictMode>
    <Providers>
      <BrowserRouter>
        <App />
      </BrowserRouter>
    </Providers>
  </StrictMode>
);
```

### Set up your routes

Define your routes declaratively with React Router:

```jsx theme={null}
// App.jsx

import { Routes, Route, Navigate } from "react-router-dom";
import { ProtectedRoute } from "./components/ProtectedRoute";
import { Login } from "./components/Login";
import { Profile } from "./components/Profile";
// ... other component imports

function App() {
  return (
    <Routes>
      <Route path="/" element={<MagicVerify />} />
      <Route path="/login" element={<LoginForm />} />
      <Route path="/profile" element={<Profile />} />
      <Route path="/magic-sent" element={<MagicSent />} />
      <Route path="/register-device" element={<RegisterDevice />} />
      <Route path="/otp-verify" element={<OtpForm />} />
    </Routes>
  );
}
```

### Create route components

Each authentication step becomes its own component. Here's an example login component:

```jsx theme={null}
// components/Login.jsx

import { useScuteClient } from "@scute/react-hooks";
import { useState } from "react";
import { useNavigate } from "react-router-dom";

export function Login() {
  const [identifier, setIdentifier] = useState("");
  const scuteClient = useScuteClient();
  const navigate = useNavigate();

  const handleSubmit = async (e) => {
    e.preventDefault();
    const { data, error } = await scuteClient.signInOrUp(identifier);

    if (error) {
      console.error("Sign in error:", error);
      return;
    }

    if (!data) {
      // Passkey verified, go to profile
      navigate("/profile");
    } else {
      // Navigate to appropriate verification step
      if (identifier.includes("@")) {
        navigate("/magic-sent", { state: { identifier } });
      } else {
        navigate("/otp-verify", { state: { identifier } });
      }
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <h2>Sign In</h2>
      <input
        type="text"
        placeholder="Email or phone"
        value={identifier}
        onChange={(e) => setIdentifier(e.target.value)}
      />
      <button type="submit">Sign In</button>
    </form>
  );
}
```

And a protected profile component:

```jsx theme={null}
// components/Profile.jsx

import { useAuth, useScuteClient } from "@scute/react-hooks";
import { useNavigate } from "react-router-dom";

export function Profile() {
  const { user } = useAuth();
  const scuteClient = useScuteClient();
  const navigate = useNavigate();

  const handleSignOut = async () => {
    await scuteClient.signOut();
    navigate("/login");
  };

  return (
    <div>
      <h2>Welcome, {user?.email}</h2>
      <pre>{JSON.stringify(user, null, 2)}</pre>
      <button onClick={handleSignOut}>Sign Out</button>
    </div>
  );
}
```

### Route navigation patterns

Use React Router's navigation hooks to move between authentication steps:

```jsx theme={null}
// Navigate programmatically
const navigate = useNavigate();
navigate("/profile");

// Navigate with state
navigate("/otp-verify", { state: { identifier } });

// Access state in destination component
const location = useLocation();
const { identifier } = location.state || {};
```
