用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/NTQ78/Todo-app --skill frontend-profile-batch-query命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
正在显示 SKILL.md
基于 SOC 职业分类
| name | frontend-profile-batch-query |
| description | Use when fetching user profiles in bulk (workaround for PostgREST cross-schema join limitation) |
Pattern for fetching multiple user profiles when PostgREST cannot join across schema boundaries.
Technical Constraint:
profiles.id → auth.users(id) (FK to auth schema)organization_members.user_id → auth.users(id) (FK to auth schema)profiles and organization_membersFailed approach:
// ❌ IMPOSSIBLE - PostgREST cannot traverse auth.users
supabase.from("organization_members").select(`
id,
user_id,
profiles ( // ❌ No direct FK relationship
email
)
`);
Error: Could not find a relationship between 'organization_members' and 'profiles' in the schema cache
Working approach:
// ✅ Batch query using .in() operator
supabase.from("profiles").select("id, email, whitelisted").in("id", userIds);
File: hooks/[Scope]/useQ_[Scope]_Profiles.ts
import { useQuery } from "@tanstack/react-query";
import { useMemo } from "react";
import { supabase, QueryData } from "@/configs/supabase/config";
import { QueryKeys } from "@/utils/query/queryKeys";
import useApp from "antd/es/app/useApp";
export type UseQ_[Scope]_Profiles_Params = {
userIds: string[];
enabled?: boolean;
};
const createProfilesQuery = (userIds: string[]) =>
supabase
.from("profiles")
.select(`
id,
email,
whitelisted,
whitelisted_at,
created_at,
updated_at
`)
.in("id", userIds);
export type [Scope]_Profiles_QueryData = QueryData<ReturnType<typeof createProfilesQuery>>;
export type [Scope]_Profile = [Scope]_Profiles_QueryData[number];
export useQ_[]_Profiles = {
{ message } = ();
{ userIds, enabled = } = params;
query = ({
: enabled && userIds. > ,
: [.....(), { : [...userIds].() }] ,
: () => {
(userIds. === ) [];
sb_FromProfiles_Select = (userIds);
(sb_FromProfiles_Select.) {
.(sb_FromProfiles_Select.);
message.();
sb_FromProfiles_Select.;
}
sb_FromProfiles_Select.;
},
});
profiles = ( query. || [], [query.]);
profilesMap = (
profiles.(
{
acc[profile.] = profile;
acc;
},
{} <, []_Profile>
),
[profiles]
);
{
query,
profiles,
profilesMap,
};
};
import { useMemo } from "react";
import { Table } from "antd";
import { useQ_[Scope]_ParentData } from "@/hooks/...";
import { useQ_[Scope]_Profiles } from "@/hooks/...";
function MyComponent() {
// Step 1: Fetch parent data with user_ids
const qParent = useQ_[Scope]_ParentData({ ... });
// Step 2: Extract user IDs
const userIds = useMemo(
() => qParent.items.map(item => item.user_id),
[qParent.items]
);
// Step 3: Batch fetch profiles
const qProfiles = useQ_[Scope]_Profiles({
userIds,
enabled: !qParent.query.isLoading
});
// Step 4: Loading states
if (qParent.query.isLoading || qProfiles.query.isLoading) {
return <Spin />;
}
if (qParent.. || qProfiles..) {
;
}
(
);
}
const qProfiles = useQ_[Scope]_Profiles({
userIds,
enabled: !qParent.query.isLoading // Wait for parent to load
});
Why: Prevents firing query before userIds array is populated
queryKey: [...QueryKeys.profiles.all(), { userIds: [...userIds].sort() }];
Why: Same set of user IDs (different order) should hit same cache
if (userIds.length === 0) return [];
Why: Prevents invalid .in("id", []) query to database
const profilesMap = useMemo(
() =>
profiles.reduce(
(acc, profile) => ({ ...acc, [profile.id]: profile }),
{} as Record<string, Profile>
),
[profiles]
);
Why: O(1) lookup performance in renders instead of O(n) with .find()
Hook: src/hooks/PageOrganization/PageOrganization_SettingsUsers/useQ_PageOrganizationSettingsUsers_Profiles.ts
Component: src/pages/Page_Organization/PageOrganization_SettingsUsers.tsx
useQ_[Scope]_Profiles (plural){ userIds: string[], enabled?: boolean }.in("id", userIds) query{ query, profiles, profilesMap }Use when deploying Cloudflare Workers, managing R2 storage, or working with Cloudflare infrastructure
Use when working with ANTD components, theme tokens, icons, forms, or feedback components (message/notification/modal)
Use when adding, referencing, or serving static assets (images, fonts, videos, 3D models) through the R2 CDN pipeline with type-safe imports