useCircles
Location: src/hooks/useCircles.js
Overview
Provides a comprehensive set of hooks for managing circles (private friend groups). Includes useCircles for listing and creating circles, useCircle for managing a single circle's members and settings, useAvailableFriends for finding friends to invite, and useCirclePosts for fetching posts within a circle.
All circle creation and invitation actions are protected by tier-aware rate limiting.
Exported Hooks
useCircles
Manages the user's circle list, including active memberships and pending invites.
function useCircles(): {
loading: boolean,
error: string | null,
rateLimitError: string | null,
myCircles: Circle[],
pendingInvites: Circle[],
createCircle: (name: string, description?: string | null) => Promise<Result>,
createDynamicCircle: (name: string, description?: string | null, rules?: Rule[]) => Promise<Result>,
acceptInvite: (circleId: string) => Promise<Result>,
declineInvite: (circleId: string) => Promise<Result>,
refetch: () => Promise<void>
}
| Property | Type | Description |
|---|---|---|
myCircles | Circle[] | Active circle memberships with member counts and user roles |
pendingInvites | Circle[] | Pending circle invitations with inviter info |
createCircle | (name, description?) => Promise<Result> | Create a static circle via create_circle RPC. Rate-limited and tier-restricted. |
createDynamicCircle | (name, description?, rules?) => Promise<Result> | Create a dynamic circle with view rules |
acceptInvite | (circleId) => Promise<Result> | Accept a circle invitation |
declineInvite | (circleId) => Promise<Result> | Decline and remove a circle invitation |
useCircle
Manages a single circle's details, members, invitations, and settings.
function useCircle(circleId: string): {
loading: boolean,
error: string | null,
rateLimitError: string | null,
circle: Circle | null,
members: Member[],
pendingInvites: Member[],
viewRules: Rule[],
userMembership: { id, role, status } | null,
// Derived state
isAdmin: boolean,
isMember: boolean,
isInvited: boolean,
isDynamic: boolean,
memberCount: number,
isOnlyAdmin: boolean,
// Actions
updateCircle: (updates: object) => Promise<Result>,
updateViewRules: (newRules: Rule[]) => Promise<Result>,
inviteFriend: (friendId: string) => Promise<Result>,
cancelInvite: (userId: string) => Promise<Result>,
removeMember: (userId: string) => Promise<Result>,
updateMemberRole: (userId: string, newRole: string) => Promise<Result>,
leaveCircle: () => Promise<Result>,
deleteCircle: () => Promise<Result>,
refetch: () => Promise<void>
}
useAvailableFriends
Fetches friends eligible to be invited to a circle (excludes existing members and blocked users).
function useAvailableFriends(circleId: string): {
loading: boolean,
error: string | null,
friends: Profile[],
refetch: () => Promise<void>
}
useCirclePosts
Fetches posts shared to a specific circle, filtering out blocked users.
function useCirclePosts(circleId: string): {
loading: boolean,
error: string | null,
posts: Post[],
hasMore: boolean,
loadMore: () => void,
refetch: () => void
}
| Property | Type | Description |
|---|---|---|
posts | Post[] | Posts in this circle with profiles, comments, images, and shared post data |
hasMore | boolean | Whether more posts are available to load |
loadMore | () => void | Load the next page (20 posts per page) |
Usage
import { useCircles, useCircle } from '../hooks/useCircles';
function CirclesList() {
const { myCircles, pendingInvites, createCircle, loading } = useCircles();
if (loading) return <Skeleton />;
return (
<div>
{pendingInvites.map(c => <InviteCard key={c.id} circle={c} />)}
{myCircles.map(c => <CircleCard key={c.id} circle={c} />)}
<button onClick={() => createCircle('My Circle')}>New Circle</button>
</div>
);
}
function CircleDetail({ circleId }) {
const { circle, members, isAdmin, inviteFriend, removeMember } = useCircle(circleId);
return (
<div>
<h2>{circle?.name}</h2>
<MemberList members={members} onRemove={isAdmin ? removeMember : null} />
</div>
);
}
Notes
- Circle creation uses a
SECURITY DEFINERRPC function that handles both circle creation and adding the creator as admin. - Dynamic circles support
circle_view_rulesfor automatic membership based on rules. useAvailableFriendsfilters out both existing members/invitees and blocked users in either direction.useCirclePostsattempts to use theget_circle_posts_excluding_blockedRPC for block filtering, with a fallback to a direct query if the RPC is not available.- Post images are sorted by
positionin the result.
Last updated: 2026-02-07