Skip to main content

useBlock

Location: src/hooks/useBlock.js

Overview

Provides multiple hooks for managing user blocking. useBlockState checks the bidirectional block state between two users. useBlockedUsers lists all users blocked by the current user. useCanInteract provides permission flags for UI decisions. useProfileVisibility uses server-side logic to determine if a profile should be shown as 404.

Critical design note: When a user is blocked by someone, they see a 404 page with no evidence that a block exists (Invariant #14: Privacy Is Infrastructure).

Exported Hooks

useBlockState

Checks bidirectional block state between the current user and another user.

function useBlockState(otherUserId: string): {
loading: boolean,
error: string | null,
iBlockedThem: boolean,
theyBlockedMe: boolean,
myBlockId: string | null,
isBlocked: boolean,
blockUser: (reason?: string | null) => Promise<{ success?: boolean, error?: string }>,
unblockUser: () => Promise<{ success?: boolean, error?: string }>,
refetch: () => Promise<void>
}
PropertyTypeDescription
iBlockedThembooleanWhether the current user has blocked the other user
theyBlockedMebooleanWhether the other user has blocked the current user
myBlockIdstring | nullID of the block record if current user blocked the other
isBlockedbooleantrue if a block exists in either direction
blockUser(reason?) => Promise<Result>Block the other user with an optional private reason. Also removes any existing friendship.
unblockUser() => Promise<Result>Remove the current user's block on the other user

useBlockedUsers

Lists all users blocked by the current user.

function useBlockedUsers(): {
loading: boolean,
error: string | null,
blockedUsers: Array<{ id, created_at, reason, blocked_user: Profile }>,
count: number,
unblockById: (userId: string) => Promise<{ success?: boolean, error?: string }>,
refetch: () => Promise<void>
}
PropertyTypeDescription
blockedUsersArrayBlocked users with profile info (display_name, username, avatar_url)
countnumberTotal number of blocked users
unblockById(userId) => Promise<Result>Unblock a user by their ID. Updates local state optimistically.

useCanInteract

Provides permission flags for UI elements based on block state.

function useCanInteract(otherUserId: string): {
loading: boolean,
canInteract: boolean,
canSendFriendRequest: boolean,
canComment: boolean,
canViewProfile: boolean,
shouldShow404: boolean,
iBlockedThem: boolean,
theyBlockedMe: boolean,
isBlocked: boolean
}
PropertyTypeDescription
canInteractbooleanNo block exists in either direction
canSendFriendRequestbooleanNo block exists in either direction
canCommentbooleanThey have not blocked the current user
canViewProfilebooleanThey have not blocked the current user
shouldShow404booleantrue if they blocked the current user (show 404, no block evidence)

useProfileVisibility

Server-side profile visibility check via can_view_profile RPC.

function useProfileVisibility(profileId: string): {
loading: boolean,
shouldShow404: boolean,
viewType: string | null
}
PropertyTypeDescription
shouldShow404booleanWhether the profile should be shown as a 404 page
viewTypestring | nullThe type of view allowed (e.g., 'not_found', 'full')

Usage

import { useBlockState, useCanInteract } from '../hooks/useBlock';

function ProfilePage({ userId }) {
const { shouldShow404, canInteract } = useCanInteract(userId);

if (shouldShow404) return <NotFound />;

return (
<div>
<ProfileContent userId={userId} />
{canInteract && <FriendButton userId={userId} />}
</div>
);
}

function BlockedUsersSettings() {
const { blockedUsers, count, unblockById, loading } = useBlockedUsers();

return (
<div>
<h3>Blocked Users ({count})</h3>
{blockedUsers.map(b => (
<div key={b.id}>
<span>{b.blocked_user.display_name}</span>
<button onClick={() => unblockById(b.blocked_user.id)}>Unblock</button>
</div>
))}
</div>
);
}

Notes

  • Blocking a user also removes any existing friendship between them.
  • The reason field on blocks is private and only visible to the blocking user.
  • useCanInteract is a convenience wrapper around useBlockState for common UI permission patterns.
  • useProfileVisibility uses a server-side RPC function for accurate block checking that cannot be bypassed client-side.

Last updated: 2026-02-07