一键导入
frontend-patterns
Expert knowledge in React patterns, component design, state management, and frontend best practices. Use for frontend development tasks.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Expert knowledge in React patterns, component design, state management, and frontend best practices. Use for frontend development tasks.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Expert knowledge in API design, authentication, caching, and backend best practices. Use for backend development tasks.
Expert knowledge in error diagnosis, debugging strategies, and self-healing patterns. Use when tasks fail or errors occur.
Expert knowledge in project planning, requirements gathering, user stories, and scope management. Use when planning new projects or features.
Expert knowledge in quality assurance gates, code quality standards, and automated checks. Use when enforcing quality standards.
Expert knowledge in testing methodologies, test patterns, and quality assurance. Use when writing tests or setting up testing infrastructure.
| name | frontend-patterns |
| description | Expert knowledge in React patterns, component design, state management, and frontend best practices. Use for frontend development tasks. |
| allowed-tools | Read, Write, Edit, Glob, Grep |
Modern React patterns and best practices for building scalable applications.
// Parent provides context, children consume it
const Tabs = ({ children, defaultTab }) => {
const [activeTab, setActiveTab] = useState(defaultTab);
return (
<TabsContext.Provider value={{ activeTab, setActiveTab }}>
<div className="tabs">{children}</div>
</TabsContext.Provider>
);
};
Tabs.List = ({ children }) => <div className="tabs-list">{children}</div>;
Tabs.Tab = ({ id, children }) => {
const { activeTab, setActiveTab } = useTabsContext();
return (
<button
className={activeTab === id ? 'active' : ''}
onClick={() => setActiveTab(id)}
>
{children}
</button>
);
};
Tabs.Panel = ({ id, children }) => {
const { activeTab } = useTabsContext();
return activeTab === id ? <div>{children}</div> : null;
};
// Usage
<Tabs defaultTab="tab1">
<Tabs.List>
<Tabs.Tab id="tab1">Tab 1</Tabs.Tab>
<Tabs.Tab id="tab2">Tab 2</Tabs.Tab>
</Tabs.List>
<Tabs.Panel id="tab1">Content 1</Tabs.Panel>
<Tabs.Panel id="tab2">Content 2</Tabs.Panel>
</Tabs>
interface MousePosition {
x: number;
y: number;
}
const MouseTracker = ({
render,
}: {
render: (pos: MousePosition) => ReactNode;
}) => {
const [position, setPosition] = useState({ x: 0, y: 0 });
useEffect(() => {
const handleMove = (e: MouseEvent) => {
setPosition({ x: e.clientX, y: e.clientY });
};
window.addEventListener('mousemove', handleMove);
return () => window.removeEventListener('mousemove', handleMove);
}, []);
return <>{render(position)}</>;
};
// Usage
<MouseTracker
render={({ x, y }) => (
<div>Mouse: {x}, {y}</div>
)}
/>
// Reusable logic extraction
function useLocalStorage<T>(key: string, initialValue: T) {
const [storedValue, setStoredValue] = useState<T>(() => {
try {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
} catch {
return initialValue;
}
});
const setValue = (value: T | ((val: T) => T)) => {
try {
const valueToStore = value instanceof Function ? value(storedValue) : value;
setStoredValue(valueToStore);
window.localStorage.setItem(key, JSON.stringify(valueToStore));
} catch (error) {
console.error(error);
}
};
return [storedValue, setValue] as const;
}
function withAuth<P extends object>(Component: ComponentType<P>) {
return function AuthenticatedComponent(props: P) {
const { user, isLoading } = useAuth();
if (isLoading) return <Spinner />;
if (!user) return <Navigate to="/login" />;
return <Component {...props} />;
};
}
// Usage
const ProtectedDashboard = withAuth(Dashboard);
interface Store {
// State
items: Item[];
isLoading: boolean;
// Actions
fetchItems: () => Promise<void>;
addItem: (item: Item) => void;
removeItem: (id: string) => void;
}
const useStore = create<Store>((set, get) => ({
items: [],
isLoading: false,
fetchItems: async () => {
set({ isLoading: true });
try {
const items = await api.getItems();
set({ items, isLoading: false });
} catch {
set({ isLoading: false });
}
},
addItem: (item) => set((state) => ({
items: [...state.items, item],
})),
removeItem: (id) => set((state) => ({
items: state.items.filter((i) => i.id !== id),
})),
}));
// Selectors for performance
const useItems = () => useStore((s) => s.items);
const useIsLoading = () => useStore((s) => s.isLoading);
// Query keys factory
const todoKeys = {
all: ['todos'] as const,
lists: () => [...todoKeys.all, 'list'] as const,
list: (filters: string) => [...todoKeys.lists(), { filters }] as const,
details: () => [...todoKeys.all, 'detail'] as const,
detail: (id: string) => [...todoKeys.details(), id] as const,
};
// Queries
export const useTodos = (filters?: string) =>
useQuery({
queryKey: todoKeys.list(filters ?? ''),
queryFn: () => fetchTodos(filters),
});
// Mutations with optimistic updates
export const useUpdateTodo = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: updateTodo,
onMutate: async (newTodo) => {
await queryClient.cancelQueries({ queryKey: todoKeys.lists() });
const previous = queryClient.getQueryData(todoKeys.lists());
queryClient.setQueryData(todoKeys.lists(), (old) =>
old?.map((t) => (t.id === newTodo.id ? newTodo : t))
);
return { previous };
},
onError: (err, newTodo, context) => {
queryClient.setQueryData(todoKeys.lists(), context?.previous);
},
onSettled: () => {
queryClient.invalidateQueries({ queryKey: todoKeys.lists() });
},
});
};
// Memoize expensive calculations
const expensiveValue = useMemo(() => {
return items.filter(x => x.active).reduce((acc, x) => acc + x.value, 0);
}, [items]);
// Memoize callbacks
const handleClick = useCallback((id: string) => {
setSelected(id);
}, []);
// Memoize components
const MemoizedList = memo(({ items }: { items: Item[] }) => (
<ul>
{items.map(item => <li key={item.id}>{item.name}</li>)}
</ul>
));
// Lazy load routes
const Dashboard = lazy(() => import('./pages/Dashboard'));
const Settings = lazy(() => import('./pages/Settings'));
// With loading fallback
<Suspense fallback={<PageSkeleton />}>
<Routes>
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/settings" element={<Settings />} />
</Routes>
</Suspense>
import { useVirtualizer } from '@tanstack/react-virtual';
function VirtualList({ items }: { items: Item[] }) {
const parentRef = useRef<HTMLDivElement>(null);
const virtualizer = useVirtualizer({
count: items.length,
getScrollElement: () => parentRef.current,
estimateSize: () => 50,
});
return (
<div ref={parentRef} style={{ height: 400, overflow: 'auto' }}>
<div style={{ height: virtualizer.getTotalSize() }}>
{virtualizer.getVirtualItems().map((virtualItem) => (
<div
key={virtualItem.key}
style={{
position: 'absolute',
top: virtualItem.start,
height: virtualItem.size,
}}
>
{items[virtualItem.index].name}
</div>
))}
</div>
</div>
);
}
class ErrorBoundary extends Component<Props, State> {
state = { hasError: false, error: null };
static getDerivedStateFromError(error: Error) {
return { hasError: true, error };
}
componentDidCatch(error: Error, info: ErrorInfo) {
console.error('Error caught:', error, info);
}
render() {
if (this.state.hasError) {
return <ErrorFallback error={this.state.error} />;
}
return this.props.children;
}
}
// Focus management
const modalRef = useRef<HTMLDivElement>(null);
useEffect(() => {
modalRef.current?.focus();
}, []);
// ARIA attributes
<button
aria-label="Close modal"
aria-expanded={isOpen}
aria-controls="modal-content"
>
<CloseIcon />
</button>
// Keyboard navigation
const handleKeyDown = (e: KeyboardEvent) => {
switch (e.key) {
case 'ArrowDown':
setFocusedIndex(i => Math.min(i + 1, items.length - 1));
break;
case 'ArrowUp':
setFocusedIndex(i => Math.max(i - 1, 0));
break;
case 'Enter':
handleSelect(focusedIndex);
break;
}
};