Skip to main content

import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem';

useUsers

A comprehensive collection of React Query hooks for admin user management -- listing, fetching, creating, updating, deleting, and validating users. Also exports query key factories, a management facade (useUsersManagement), and a legacy imperative API (useUsersLegacy).

Source: template/hooks/use-users.ts

Exported Hooks

HookPurpose
useUsersPaginated/filtered user list query
useUserSingle user detail query
useUserStatsUser count statistics query
useCreateUserCreate user mutation
useUpdateUserUpdate user mutation
useDeleteUserDelete user mutation
useCheckUsernameUsername availability mutation
useCheckEmailEmail availability mutation
useUsersManagementFacade that bundles all hooks and cache utilities
useUsersLegacyImperative API for backward compatibility (deprecated)

Exported Constants

const userQueryKeys = {
all: ['users'],
lists: () => [...userQueryKeys.all, 'list'],
list: (options: UserListOptions) => [...userQueryKeys.lists(), options],
details: () => [...userQueryKeys.all, 'detail'],
detail: (id: string) => [...userQueryKeys.details(), id],
stats: () => [...userQueryKeys.all, 'stats'],
};

These query keys are exported for external cache operations.


useUsers

Fetches a paginated and filtered list of users.

Signature

function useUsers(options?: UserListOptions): UseQueryResult<UserListResponse>;

Parameters

ParameterTypeDefaultDescription
optionsUserListOptions{}Filtering and pagination parameters passed as query string to the API

Cache Configuration

SettingValue
staleTime5 minutes
gcTime10 minutes

Usage

function UserList() {
const { data, isLoading, error } = useUsers({ page: 1, limit: 20 });

if (isLoading) return <Spinner />;
if (error) return <ErrorBanner message={error.message} />;

return (
<div>
<p>Total: {data?.total}</p>
{data?.users.map((user) => (
<UserRow key={user.id} user={user} />
))}
</div>
);
}

useUser

Fetches a single user by ID.

Signature

function useUser(id: string, enabled?: boolean): UseQueryResult<UserData | null>;

Parameters

ParameterTypeDefaultDescription
idstring--User ID to fetch
enabledbooleantrueSet to false to skip the query; also automatically disabled when id is empty

Cache Configuration

SettingValue
staleTime5 minutes
gcTime10 minutes

Usage

function UserDetail({ userId }: { userId: string }) {
const { data: user, isLoading } = useUser(userId);

if (isLoading) return <Spinner />;
if (!user) return <NotFound />;

return <ProfileCard user={user} />;
}

useUserStats

Fetches aggregate user statistics.

Signature

function useUserStats(): UseQueryResult<{ total: number; active: number; inactive: number }>;

Cache Configuration

SettingValue
staleTime10 minutes
gcTime15 minutes

Usage

function UserStatsCards() {
const { data: stats } = useUserStats();

return (
<div className="grid grid-cols-3 gap-4">
<StatCard label="Total" value={stats?.total} />
<StatCard label="Active" value={stats?.active} />
<StatCard label="Inactive" value={stats?.inactive} />
</div>
);
}

useCreateUser

Creates a new user. Automatically invalidates user list and stats caches on success.

Signature

function useCreateUser(): UseMutationResult<UserData, Error, CreateUserRequest>;

Usage

function CreateUserForm() {
const { mutate: createUser, isPending } = useCreateUser();

const handleSubmit = (formData: CreateUserRequest) => {
createUser(formData, {
onSuccess: (user) => toast.success(`User ${user.name} created`),
onError: (err) => toast.error(err.message),
});
};

return <UserForm onSubmit={handleSubmit} loading={isPending} />;
}

useUpdateUser

Updates an existing user. On success, updates the individual user cache entry and invalidates list/stats caches.

Signature

function useUpdateUser(): UseMutationResult<UserData, Error, { id: string; userData: UpdateUserRequest }>;

Usage

function EditUserForm({ user }: { user: UserData }) {
const { mutate: updateUser, isPending } = useUpdateUser();

const handleSave = (updates: UpdateUserRequest) => {
updateUser({ id: user.id, userData: updates });
};

return <UserForm defaultValues={user} onSubmit={handleSave} loading={isPending} />;
}

useDeleteUser

Deletes a user by ID. On success, removes the user from the detail cache and invalidates list/stats caches.

Signature

function useDeleteUser(): UseMutationResult<void, Error, string>;

Usage

function DeleteUserButton({ userId }: { userId: string }) {
const { mutate: deleteUser, isPending } = useDeleteUser();

return (
<button
onClick={() => deleteUser(userId)}
disabled={isPending}
>
{isPending ? 'Deleting...' : 'Delete User'}
</button>
);
}

useCheckUsername

Checks if a username is available. Accepts an optional excludeId to exclude the current user during edits.

Signature

function useCheckUsername(): UseMutationResult<boolean, Error, { username: string; excludeId?: string }>;

Usage

function UsernameField({ currentUserId }: Props) {
const { mutateAsync: checkUsername } = useCheckUsername();

const validateUsername = async (username: string) => {
const available = await checkUsername({ username, excludeId: currentUserId });
return available || 'Username already taken';
};

return <input {...register('username', { validate: validateUsername })} />;
}

useCheckEmail

Checks if an email address is available. Same pattern as useCheckUsername.

Signature

function useCheckEmail(): UseMutationResult<boolean, Error, { email: string; excludeId?: string }>;

useUsersManagement

A facade hook that returns all individual hooks plus cache invalidation utilities. Useful when a component needs access to multiple user operations.

Signature

function useUsersManagement(): UsersManagementReturn;

Return Value

const {
// Query hooks (call these as hooks in your component)
useUsers,
useUser,
useUserStats,

// Mutation hooks
useCreateUser,
useUpdateUser,
useDeleteUser,
useCheckUsername,
useCheckEmail,

// Cache utilities
invalidateUsers, // () => void -- Invalidate all user queries
invalidateUser, // (id: string) => void -- Invalidate a specific user detail query
invalidateUserLists, // () => void -- Invalidate user list queries only
invalidateUserStats, // () => void -- Invalidate user stats query only
} = useUsersManagement();

useUsersLegacy (Deprecated)

An imperative API preserved for backward compatibility. Prefer the React Query-based hooks above for new code.

Signature

function useUsersLegacy(): UseUsersLegacyReturn;

Return Value

const {
loading, // boolean
error, // string | null
getUsers, // (options?: UserListOptions) => Promise<UserListResponse>
getUser, // (id: string) => Promise<UserData | null>
createUser, // (userData: CreateUserRequest) => Promise<UserData | null>
updateUser, // (id: string, userData: UpdateUserRequest) => Promise<UserData | null>
deleteUser, // (id: string) => Promise<boolean>
getUserStats, // () => Promise<{ total; active; inactive } | null>
checkUsername, // (username: string, excludeId?: string) => Promise<boolean>
checkEmail, // (email: string, excludeId?: string) => Promise<boolean>
clearError, // () => void
} = useUsersLegacy();
Deprecated

useUsersLegacy does not benefit from React Query caching, deduplication, or automatic refetching. Use the individual React Query hooks (useUsers, useCreateUser, etc.) for new development.

Implementation Details

API Layer

All hooks share a private userApi object that wraps serverClient from @/lib/api/server-api-client:

MethodHTTPEndpoint
getUsersGET/api/admin/users?...
getUserGET/api/admin/users/:id
createUserPOST/api/admin/users
updateUserPUT/api/admin/users/:id
deleteUserDELETE/api/admin/users/:id
getUserStatsGET/api/admin/users/stats
checkUsernamePOST/api/admin/users/check-username
checkEmailPOST/api/admin/users/check-email

Cache Invalidation Strategy

MutationCaches Invalidated
createUserUser lists, user stats
updateUserSpecific user detail (optimistic set), user lists, user stats
deleteUserSpecific user detail (removed), user lists, user stats

Dependencies

DependencyPurpose
@tanstack/react-queryuseQuery, useMutation, useQueryClient for data fetching and caching
@/lib/api/server-api-clientserverClient for HTTP calls, apiUtils for response handling
@/lib/types/userUserData, CreateUserRequest, UpdateUserRequest, UserListOptions, UserListResponse types
  • useAdminUsers -- Admin user management with additional admin-specific operations
  • useCurrentUser -- Fetches the currently authenticated user (different from admin user listing)
  • useUserUtils -- Derived user properties like display role and online status
  • useRoles -- Role data used in user management forms