# React Runtime Environment Variables — useRep() Hooks
> Access runtime environment variables in React with useRep() and useRepSecure() hooks. Synchronous reads, encrypted secrets, and automatic hot reload re-rendering.
Source: https://rep-protocol.dev/frameworks/react/
## Installation
```bash
npm install @rep-protocol/react @rep-protocol/sdk
```
## Basic usage
```tsx
import { useRep, useRepSecure } from '@rep-protocol/react';
function App() {
// PUBLIC tier — synchronous, no loading state
const apiUrl = useRep('API_URL', 'http://localhost:3000');
const flags = useRep('FEATURE_FLAGS', '').split(',');
// SENSITIVE tier — async, renders null until resolved
const { value: analyticsKey, loading, error } = useRepSecure('ANALYTICS_KEY');
if (loading) return Loading...;
if (error) return Config error: {error.message};
return (
API: {apiUrl}
Analytics: {analyticsKey}
);
}
```
## Migration from Vite / CRA
**Before:**
```typescript
// src/config.ts
export const API_URL = import.meta.env.VITE_API_URL;
export const FEATURE_FLAGS = import.meta.env.VITE_FEATURE_FLAGS?.split(',') ?? [];
```
**After:**
```typescript
// src/config.ts
import { rep } from '@rep-protocol/sdk';
export const API_URL = rep.get('API_URL', 'http://localhost:3000');
export const FEATURE_FLAGS = rep.get('FEATURE_FLAGS', '')?.split(',').filter(Boolean) ?? [];
```
Or use the codemod for automated migration:
```bash
npx @rep-protocol/codemod --framework vite src/
```
## `useRep(key, defaultValue?)`
Reads a **PUBLIC** tier variable. Synchronous — no loading state, no Suspense.
```tsx
const value = useRep('API_URL'); // string | undefined
const value = useRep('API_URL', 'fallback'); // string (never undefined)
```
- Returns the value from the injected payload immediately
- Returns `defaultValue` (or `undefined`) if the variable is not present
- Automatically re-renders when the variable changes via hot reload
- Unsubscribes on unmount
## `useRepSecure(key)`
Reads a **SENSITIVE** tier variable. Async — fetches a session key on first call.
```tsx
const { value, loading, error } = useRepSecure('ANALYTICS_KEY');
// value: string | null — null until resolved
// loading: boolean — true while fetching
// error: Error | null — set if fetch or decryption fails
```
- Starts with `{ value: null, loading: true, error: null }`
- The decrypted value is cached by the SDK for the page lifetime
- Re-fetches if the `key` prop changes
## Hot reload
Both hooks subscribe to the gateway's SSE stream when `--hot-reload` is enabled. Components re-render automatically when config changes. If hot reload is not available, hooks still work — they just won't update after initial render.
> **Note**
>
> `useRepSecure` subscribes to hot reload for re-rendering, but sensitive variable decryption requires a new session key — which means a full component remount for updated sensitive values.
## Development mode
Without the gateway running, `useRep()` returns `undefined`. Three approaches:
**Vite plugin (recommended)**
```bash
npm install -D @rep-protocol/vite
```
```ts
// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { repPlugin } from '@rep-protocol/vite';
export default defineConfig({
plugins: [react(), repPlugin()],
});
```
The plugin reads `.env.local` and injects the REP payload during `vite dev` — no gateway needed. Just run `npm run dev` as normal. Using Next.js instead? See the [Next.js plugin reference](/reference/plugins/next/) — same idea, `RepScript` instead of `repPlugin()`. Full option list: [Vite plugin reference](/reference/plugins/vite/).
**Default values**
```tsx
const apiUrl = useRep('API_URL', 'http://localhost:3000');
```
**CLI dev server**
```bash
# Terminal 1: Vite dev server
npm run dev
# Terminal 2: REP gateway proxy
npx @rep-protocol/cli dev --proxy http://localhost:5173
```
## Requirements
- React >= 16.8 (hooks support)
- `@rep-protocol/sdk` as a peer dependency
For the full API reference, see [React Adapter Reference](/reference/adapters/react/).