Skip to main content
react-fieldguide This skill should be used when building React components with TypeScript, typing hooks, handling events, or when React TypeScript, React 19, Server Components are mentioned. Covers type-safe patterns for React 18-19 including generic components, proper event typing, and TanStack Router integration.
설치로 이동 Skills Marketplace 커뮤니티가 만든 AI 스킬을 발견하고 탐색하세요.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/outfitter-dev/outfitter --skill react-fieldguide명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
Zip 다운로드 다운로드 중... 이 저장소의 다른 Skills Patterns for @outfitter/daemon including lifecycle management, IPC communication, health checks, and PID files. Use when building background services, daemons, or when "daemon", "IPC", "health check", "background service", or "@outfitter/daemon" are mentioned.
Creates handlers, CLI commands, MCP tools, and daemon services following Outfitter Dev Kit conventions. Use when adding new components to a project, scaffolding code, or when "create handler", "new command", "add tool", or "daemon service" are mentioned.
Deep patterns for @outfitter/mcp including tool registration, Zod schemas, resources, and server configuration. Use when building MCP servers, registering tools, defining resources, or when "MCP server", "MCP tool", "registerTool", or "@outfitter/mcp" are mentioned.
name react-fieldguide description This skill should be used when building React components with TypeScript, typing hooks, handling events, or when React TypeScript, React 19, Server Components are mentioned. Covers type-safe patterns for React 18-19 including generic components, proper event typing, and TanStack Router integration. metadata {"version":"1.0.1"}
React TypeScript
Type-safe React = compile-time guarantees = confident refactoring.
<when_to_use>
Building typed React components
Implementing generic components
Typing event handlers, forms, refs
Using React 19 features (Actions, Server Components, use())
TanStack Router integration
Custom hooks with proper typing
NOT for: non-React TypeScript, vanilla JS React
</when_to_use>
<react_19_changes>
React 19 breaking changes require migration. Key patterns:
ref as prop - forwardRef deprecated:
type ButtonProps = {
ref ?: React .Ref <HTMLButtonElement >;
} & React .ComponentPropsWithoutRef <'button' >;
function Button ({ ref, children, ...props }: ) {
;
}
ButtonProps
return
<button ref ={ref} {...props }> {children}</button >
useActionState - replaces useFormState:
import { useActionState } from 'react' ;
type FormState = { errors ?: string []; success ?: boolean };
function Form ( ) {
const [state, formAction, isPending] = useActionState (submitAction, {});
return <form action ={formAction} > ...</form > ;
}
use() - unwraps promises/context:
function UserProfile ({ userPromise }: { userPromise: Promise <User> } ) {
const user = use (userPromise);
return <div > {user.name}</div > ;
}
Props - extend native elements:
type ButtonProps = {
variant : 'primary' | 'secondary' ;
} & React .ComponentPropsWithoutRef <'button' >;
function Button ({ variant, children, ...props }: ButtonProps ) {
return <button className ={variant} {...props }> {children}</button > ;
}
type Props = {
children : React .ReactNode ;
icon : React .ReactElement ;
render : (data : T ) => React .ReactNode ;
};
Discriminated unions for variant props:
type ButtonProps =
| { variant : 'link' ; href : string }
| { variant : 'button' ; onClick : () => void };
function Button (props : ButtonProps ) {
if (props.variant === 'link' ) {
return <a href ={props.href} > Link</a > ;
}
return <button onClick ={props.onClick} > Button</button > ;
}
Use specific event types for accurate target typing:
function handleClick (e : React .MouseEvent <HTMLButtonElement > ) {
e.currentTarget .disabled = true ;
}
function handleSubmit (e : React .FormEvent <HTMLFormElement > ) {
e.preventDefault ();
const formData = new FormData (e.currentTarget );
}
function handleChange (e : React .ChangeEvent <HTMLInputElement > ) {
console .log (e.target .value );
}
function handleKeyDown (e : React .KeyboardEvent <HTMLInputElement > ) {
if (e.key === "Enter" ) e.currentTarget .blur ();
}
useState - explicit for unions/null:
const [user, setUser] = useState<User | null >(null );
const [status, setStatus] = useState<"idle" | "loading" >("idle" );
useRef - null for DOM, value for mutable:
const inputRef = useRef<HTMLInputElement >(null );
const countRef = useRef<number >(0 );
useReducer - discriminated unions for actions:
type Action = { type : "increment" } | { type : "set" ; payload : number };
function reducer (state : State , action : Action ): State {
switch (action.type ) {
case "set" :
return { ...state, count : action.payload };
default :
return state;
}
}
Custom hooks - tuple returns with as const:
function useToggle (initial = false ) {
const [value, setValue] = useState (initial);
const toggle = ( ) => setValue ((v ) => !v);
return [value, toggle] as const ;
}
useContext - null guard pattern:
const UserContext = createContext<User | null >(null );
function useUser ( ) {
const user = useContext (UserContext );
if (!user) throw new Error ("useUser outside UserProvider" );
return user;
}
See hooks.md for useCallback, useMemo, useImperativeHandle, useSyncExternalStore.
Generic components infer types from props - no manual annotations at call site.
Pattern - keyof T for column keys, render props for custom rendering:
type Column <T> = {
key : keyof T;
header : string ;
render ?: (value : T[keyof T], item : T ) => React .ReactNode ;
};
type TableProps <T> = {
data : T[];
columns : Column <T>[];
keyExtractor : (item : T ) => string | number ;
};
function Table <T>({ data, columns, keyExtractor }: TableProps <T>) {
return (
<table >
<thead >
<tr > {columns.map(col => <th key ={String(col.key)} > {col.header}</th > )}</tr >
</thead >
<tbody >
{data.map(item => (
<tr key ={keyExtractor(item)} >
{columns.map(col => (
<td key ={String(col.key)} >
{col.render ? col.render(item[col.key], item) : String(item[col.key])}
</td >
))}
</tr >
))}
</tbody >
</table >
);
}
Constrained generics for required properties:
type HasId = { id : string | number };
function List <T extends HasId >({ items }: { items : T[] }) {
return <ul > {items.map(item => <li key ={item.id} > ...</li > )}</ul > ;
}
React 19 Server Components run on server, can be async.
export default async function UserPage ({ params }: { params: { id: string } } ) {
const user = await fetchUser (params.id );
return <div > {user.name}</div > ;
}
Server Actions - 'use server' for mutations:
'use server' ;
export async function updateUser (userId : string , formData : FormData ) {
await db.user .update ({ where : { id : userId }, data : { ... } });
revalidatePath (`/users/${userId} ` );
}
'use client' ;
import { useActionState } from 'react' ;
import { updateUser } from '@/actions/user' ;
function UserForm ({ userId }: { userId: string } ) {
const [state, formAction, isPending] = useActionState (
(prev, formData ) => updateUser (userId, formData), {}
);
return <form action ={formAction} > ...</form > ;
}
use() for promise handoff :
async function Page ( ) {
const userPromise = fetchUser ('123' );
return <UserProfile userPromise ={userPromise} /> ;
}
'use client' ;
function UserProfile ({ userPromise }: { userPromise: Promise <User> } ) {
const user = use (userPromise);
return <div > {user.name}</div > ;
}
TanStack Router = type-safe routes, params, search params, loader data.
Route with Zod validation :
import { createRoute } from "@tanstack/react-router" ;
import { z } from "zod" ;
const userRoute = createRoute ({
path : "/users/$userId" ,
component : UserPage ,
loader : async ({ params }) => ({ user : await fetchUser (params.userId ) }),
validateSearch : z.object ({
tab : z.enum (["profile" , "settings" ]).optional (),
page : z.number ().int ().positive ().default (1 ),
}),
});
function UserPage ( ) {
const { user } = useLoaderData ({ from : userRoute.id });
const { tab, page } = useSearch ({ from : userRoute.id });
const { userId } = useParams ({ from : userRoute.id });
}
navigate ({
to : "/users/$userId" ,
params : { userId },
search : { tab : "profile" },
});
See tanstack-router.md for nested routes, beforeLoad, error handling, React Query integration.
Specific event types (MouseEvent, ChangeEvent, etc)
Explicit useState for unions/null
ComponentPropsWithoutRef for native element extension
Discriminated unions for variant props
as const for tuple returns
ref as prop in React 19 (no forwardRef)
useActionState for form actions
Zod validation for TanStack Router search params
any for event handlers
JSX.Element for children (use ReactNode)
forwardRef in React 19+
useFormState (deprecated)
Forget null handling for DOM refs
Mix Server/Client components in same file
Await promises when passing to use()
hooks.md - useState, useRef, useReducer, useContext, custom hooks
event-handlers.md - all event types, generic handlers
react-19-patterns.md - useActionState, use(), useOptimistic, migration
generic-components.md - Table, Select, List, Modal patterns
server-components.md - async components, Server Actions, streaming
tanstack-router.md - typed routes, search params, navigation