markhamsquareventures

react

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

markhamsquareventures 0 Updated 4mo ago
GitHub

Install

npx skillscat add markhamsquareventures/essentials/react

Install via the SkillsCat registry.

SKILL.md

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)