React 18+ development patterns including components, hooks, state management, API integration, and accessibility. Use when: (1) building React components, (2) designing user interfaces, (3) implementing state management, (4) writing frontend tests.
React 18+ patterns for building modern, accessible, type-safe user interfaces.
import { FC } from 'react';
interface {Component}Props {
title: string;
variant?: 'primary' | 'secondary';
disabled?: boolean;
onClick?: () => void;
}
export const {Component}: FC<{Component}Props> = ({
title,
variant = 'primary',
disabled = false,
onClick,
}) => {
return (
<button
className={`btn btn-${variant}`}
disabled={disabled}
onClick={onClick}
>
{title}
</button>
);
};
import { FC } from 'react';
import { useQuery } from '@tanstack/react-query';
import { {entity}Service } from '@/services/{entity}Service';
import type { {Entity}Dto } from '@/types';
interface {Entity}ListProps {
onSelect: (entity: {Entity}Dto) => void;
}
export const {Entity}List: FC<{Entity}ListProps> = ({ onSelect }) => {
const { data, isLoading, error } = useQuery({
queryKey: ['{entities}'],
queryFn: {entity}Service.getAll,
});
if (isLoading) return <Skeleton count={5} />;
if (error) return <ErrorMessage error={error} />;
if (!data?.length) return <EmptyState message="No items found" />;
return (
<ul role="list" aria-label="{Entity} list">
{data.map((entity) => (
<{Entity}Card
key={entity.id}
entity={entity}
onClick={() => onSelect(entity)}
/>
))}
</ul>
);
};
import { api } from '@/lib/api';
import type { {Entity}Dto, Create{Entity}Dto, PagedResult } from '@/types';
export const {entity}Service = {
getAll: async (params?: { skip?: number; take?: number }): Promise<PagedResult<{Entity}Dto>> => {
const response = await api.get('/api/app/{entities}', { params });
return response.data;
},
getById: async (id: string): Promise<{Entity}Dto> => {
const response = await api.get(`/api/app/{entities}/${id}`);
return response.data;
},
create: async (data: Create{Entity}Dto): Promise<{Entity}Dto> => {
const response = await api.post('/api/app/{entities}', data);
return response.data;
},
update: async (id: string, data: Partial<Create{Entity}Dto>): Promise<{Entity}Dto> => {
const response = await api.put(`/api/app/{entities}/${id}`, data);
return response.data;
},
delete: async (id: string): Promise<void> => {
await api.delete(`/api/app/{entities}/${id}`);
},
};
## Screen: [Screen Name]
### Layout
┌─────────────────────────────────────┐
│ [Header: Logo | Nav | User Menu] │
├─────────────────────────────────────┤
│ [Sidebar] │ [Main Content] │
│ │ │
│ - Nav 1 │ ┌─────────┐ ┌─────────┐│
│ - Nav 2 │ │ Card 1 │ │ Card 2 ││
│ - Nav 3 │ └─────────┘ └─────────┘│
├─────────────────────────────────────┤
│ [Footer] │
└─────────────────────────────────────┘
### Components
- Header: Logo, Navigation, UserMenu
- Sidebar: NavItem[], CollapsibleSection
- Card: Image?, Title, Description, ActionButton
### Interactions
- Card click → Navigate to detail
- NavItem hover → Show tooltip
### States
- Loading: Skeleton placeholders
- Empty: "No items" + CTA
- Error: Error banner + retry
## Component: [ComponentName]
### Props
| Prop | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| variant | 'primary' \| 'secondary' | No | 'primary' | Visual style |
| disabled | boolean | No | false | Disable interactions |
| onClick | () => void | No | - | Click handler |
### States
- Default, Hover, Active, Disabled, Loading, Error
### Accessibility
- Role: button
- Keyboard: Enter/Space to activate
- aria-label required when icon-only
// queries.ts
export const use{Entity}Query = (id: string) => useQuery({
queryKey: ['{entity}', id],
queryFn: () => {entity}Service.getById(id),
staleTime: 5 * 60 * 1000, // 5 minutes
});
export const use{Entities}Query = (params?: ListParams) => useQuery({
queryKey: ['{entities}', params],
queryFn: () => {entity}Service.getAll(params),
});
// mutations.ts
export const useCreate{Entity} = () => useMutation({
mutationFn: {entity}Service.create,
onSuccess: () => queryClient.invalidateQueries(['{entities}']),
});
import { create } from 'zustand';
interface UIStore {
sidebarOpen: boolean;
toggleSidebar: () => void;
selectedId: string | null;
setSelectedId: (id: string | null) => void;
}
export const useUIStore = create<UIStore>((set) => ({
sidebarOpen: true,
toggleSidebar: () => set((s) => ({ sidebarOpen: !s.sidebarOpen })),
selectedId: null,
setSelectedId: (id) => set({ selectedId: id }),
}));
ui/
├── src/
│ ├── components/ # Reusable UI components
│ │ ├── common/ # Buttons, inputs, cards
│ │ └── layout/ # Header, sidebar, footer
│ ├── features/ # Feature-based modules
│ │ └── {feature}/ # Feature module
│ ├── hooks/ # Custom React hooks
│ ├── services/ # API service layer
│ ├── store/ # State management
│ ├── types/ # TypeScript types
│ └── utils/ # Utility functions
├── tests/
│ ├── unit/ # Component unit tests
│ ├── integration/ # Feature integration tests
│ └── e2e/ # Playwright E2E tests
└── public/
import { render, screen, fireEvent } from '@testing-library/react';
import { {Component} } from './{Component}';
describe('{Component}', () => {
it('renders with title', () => {
render(<{Component} title="Test" />);
expect(screen.getByText('Test')).toBeInTheDocument();
});
it('calls onClick when clicked', () => {
const handleClick = jest.fn();
render(<{Component} title="Test" onClick={handleClick} />);
fireEvent.click(screen.getByRole('button'));
expect(handleClick).toHaveBeenCalledTimes(1);
});
it('is disabled when disabled prop is true', () => {
render(<{Component} title="Test" disabled />);
expect(screen.getByRole('button')).toBeDisabled();
});
});
| Topic | File |
|-------|------|
| TypeScript types | typescript-advanced-types skill |
| ES6+ patterns | modern-javascript-patterns skill |
| Testing patterns | javascript-testing-patterns skill |
npx skills add thapaliyabikendra/react-development-patterns下载完整 Skill 目录,包含 SKILL.md 及所有相关文件
Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer