useRateLimit
Location: src/hooks/useRateLimit.js
Overview
Provides hooks and utilities for checking and enforcing rate limits on the frontend. Includes useRateLimit for general rate limit enforcement, useRateLimitStatus for querying current rate limit state, and utility functions for detecting and parsing rate limit errors. Each action type has user-friendly error messages.
Exports
RATE_LIMIT_ACTIONS
Action type constants used across the application:
| Constant | Value | Description |
|---|---|---|
FRIEND_REQUEST | 'friend_request' | Sending friend requests |
MESSAGE_NEW_CONVERSATION | 'message_new_conversation' | Starting new conversations |
POST_CREATE | 'post_create' | Creating posts |
LOGIN_ATTEMPT | 'login_attempt' | Login attempts |
PROFILE_VIEW | 'profile_view' | Viewing profiles |
REPORT_SUBMIT | 'report_submit' | Submitting reports |
CIRCLE_CREATE | 'circle_create' | Creating circles |
CIRCLE_INVITE | 'circle_invite' | Sending circle invitations |
isRateLimitError (function)
function isRateLimitError(error: any): boolean
Checks if an error is a rate limit error by looking for "Rate limit exceeded", "too many", or "Try again" in the message.
parseRateLimitError (function)
function parseRateLimitError(error: any, actionType: string): string
Returns a user-friendly error message for the given action type.
useRateLimitStatus
Queries the current rate limit status for a specific action type.
function useRateLimitStatus(actionType: string): {
status: object | null,
loading: boolean,
error: object | null,
checkStatus: () => Promise<void>,
getMessage: () => string | null,
isLimited: boolean,
remaining: number | null,
resetAt: Date | null
}
| Parameter | Type | Required | Description |
|---|---|---|---|
actionType | string | Yes | The rate limit action type to check |
| Property | Type | Description |
|---|---|---|
status | object | null | Raw status from get_rate_limit_status RPC |
isLimited | boolean | Whether the limit has been reached |
remaining | number | null | Number of remaining actions allowed |
resetAt | Date | null | When the rate limit resets |
getMessage | () => string | null | Returns appropriate message (exceeded or remaining count) |
checkStatus | () => Promise<void> | Manually check the current status |
useRateLimit
General-purpose rate limit enforcement hook.
function useRateLimit(): {
rateLimitError: string | null,
checkLimit: (actionType: string, targetId?: string | null) => Promise<{ allowed: boolean, message: string | null, remaining?: number }>,
recordAction: (actionType: string, targetId?: string | null) => Promise<void>,
handleError: (error: any, actionType: string) => boolean,
clearError: () => void,
isRateLimitError: (error: any) => boolean
}
| Property | Type | Description |
|---|---|---|
rateLimitError | string | null | Current rate limit error message |
checkLimit | (actionType, targetId?) => Promise<Result> | Check rate limit via check_rate_limit RPC. Fails open (allows action) if the check itself errors. |
recordAction | (actionType, targetId?) => Promise<void> | Record a completed action via record_rate_limit_action RPC |
handleError | (error, actionType) => boolean | Check if an error is rate-limit-related and set the error message. Returns true if it was a rate limit error. |
clearError | () => void | Clear the rate limit error state |
isRateLimitError | (error) => boolean | Check if an error is a rate limit error |
Usage
import { useRateLimit, RATE_LIMIT_ACTIONS } from '../hooks/useRateLimit';
function CreatePostButton({ onPost }) {
const { checkLimit, recordAction, rateLimitError, clearError } = useRateLimit();
const handlePost = async (content) => {
const { allowed, message } = await checkLimit(RATE_LIMIT_ACTIONS.POST_CREATE);
if (!allowed) return;
const result = await createPost(content);
if (result.success) {
await recordAction(RATE_LIMIT_ACTIONS.POST_CREATE);
onPost(result);
}
};
return (
<div>
{rateLimitError && <p className="error">{rateLimitError}</p>}
<button onClick={handlePost}>Post</button>
</div>
);
}
Notes
- Rate limit checks fail open (allow the action) if the RPC call itself fails, preventing rate limit infrastructure issues from blocking normal usage.
- User-friendly messages are provided for each action type (e.g., "You've sent too many friend requests today. Please try again tomorrow.").
recordActionshould be called after a successful action, not before.- Profile view tracking was intentionally removed as it violates Invariant #16 (AI Never Observes Individuals).
Last updated: 2026-02-07