react

markhamsquareventures's avatarfrom markhamsquareventures

How to work effectively with React, always use when developing frontend components

⭐0stars🔀0forks📁View on GitHub🕐Updated Jan 8, 2026

When & Why to Use This Skill

This Claude skill provides a comprehensive framework and set of best practices for developing modern frontend components using React 19 and TypeScript. It is specifically optimized for the Laravel and Inertia.js ecosystem, focusing on seamless server-side data integration, type safety, and high-performance rendering via the React Compiler. By following these instructions, developers can ensure state consistency, eliminate redundant client-side fetching, and maintain a clean, scalable directory structure.

Use Cases

  • Building type-safe React components and pages within a Laravel/Inertia.js project to ensure the server remains the single source of truth.
  • Implementing UI primitives and shared components using shadcn/ui and Tailwind CSS while adhering to standardized directory structures.
  • Optimizing application performance by leveraging the React 19 Compiler and following modern state management patterns without unnecessary memoization.
  • Standardizing codebase conventions for TypeScript interfaces, file naming, and event handling to improve team collaboration and code maintainability.
namereact
descriptionHow to work effectively with React, always use when developing frontend components

React

Instructions

This project uses React 19 with TypeScript and the React Compiler enabled via babel-plugin-react-compiler.

Component Structure

  • Pages live in resources/js/pages/ and are rendered via Inertia
  • Shared components live in resources/js/components/
  • UI primitives (shadcn/ui) live in resources/js/components/ui/
  • Custom hooks live in resources/js/hooks/

Page Props from Controllers

Always receive page data as props from the Laravel controller via Inertia. Do NOT fetch data client-side or use useEffect to load page data.

// In Laravel controller public function edit(Project $project): Response { return Inertia::render('projects/edit', [ 'project' => $project->load('client'), 'clients' => Client::orderBy('name')->get(), ]); } // In React page component import { Project, Client } from '@/types';

interface EditProjectProps { project: Project; clients: Client[]; }

export default function EditProject({ project, clients }: EditProjectProps) { return ( <Form action={update({ project: project.id }).url} method="patch"> {/* Form fields using project and clients data */} ); }

This pattern ensures:

  • State consistency - The server is the single source of truth; no client-side caching or stale data issues
  • Data is loaded server-side before the page renders
  • No loading states needed for initial page data
  • SEO-friendly server-rendered content
  • Type-safe props matching controller output

TypeScript Conventions

  • All component props should be typed explicitly
  • Use interfaces for object shapes, defined in resources/js/types/index.d.ts
  • Prefer React.ComponentProps<"element"> for extending native element props
  • Use path aliases: @/components, @/hooks, @/lib, @/types
import { cn } from '@/lib/utils';

interface CardProps { title: string; description?: string; className?: string; children: React.ReactNode; }

export function Card({ title, description, className, children }: CardProps) { return ( <div className={cn('rounded-lg border p-4', className)}>

{title}

{description &&

{description}

} {children} ); }

React 19 + React Compiler

  • The React Compiler automatically memoizes components and hooks
  • Do NOT manually add useMemo, useCallback, or React.memo unless profiling shows a specific need
  • Write straightforward code and let the compiler optimize

State Management

  • Use React's built-in useState and useReducer for local state
  • Use Inertia's shared data for server-provided state (accessed via usePage())
  • For form state, use the Inertia <Form> component (see inertia skill)
import { usePage } from '@inertiajs/react'; import { SharedData } from '@/types';

export function UserGreeting() { const { auth } = usePage().props;

return <span>Hello, {auth.user.name}</span>;

}

Event Handlers

  • Use inline arrow functions for simple handlers
  • Extract to named functions only when logic is complex or reused

Conditional Rendering

  • Use early returns for guard clauses
  • Prefer && for simple conditionals, ternaries for if/else
  • Use separate components for complex conditional logic
// Early return for loading state function DataDisplay({ data, isLoading }: Props) { if (isLoading) { return ; }
return (
    <div>
        {data.items.length > 0 && <ItemList items={data.items} />}
        {data.error ? <ErrorMessage error={data.error} /> : <SuccessIndicator />}
    </div>
);

}

File Naming

  • Components: PascalCase (UserCard.tsx)
  • Hooks: camelCase with use prefix (useClipboard.ts)
  • Utilities: camelCase (formatDate.ts)
  • Pages: kebab-case matching the route (edit.tsx, create.tsx, index.tsx)