Master React with TypeScript using hooks, context, and modern patterns for scalable applications.
# Modern React TypeScript Development
Master modern React development with TypeScript using Google Antigravity IDE. This comprehensive guide covers component patterns, hooks, and type-safe state management.
## Why React TypeScript?
TypeScript brings type safety and better developer experience to React. Google Antigravity IDE's Gemini 3 engine provides intelligent type inference and component suggestions.
## Component Patterns
```typescript
// components/Button.tsx
import { forwardRef, ButtonHTMLAttributes, ReactNode } from "react";
interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
variant?: "primary" | "secondary" | "ghost";
size?: "sm" | "md" | "lg";
loading?: boolean;
leftIcon?: ReactNode;
rightIcon?: ReactNode;
}
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
(
{
variant = "primary",
size = "md",
loading = false,
leftIcon,
rightIcon,
children,
disabled,
className,
...props
},
ref
) => {
const baseStyles = "inline-flex items-center justify-center font-medium rounded-lg transition-colors";
const variants = {
primary: "bg-blue-600 text-white hover:bg-blue-700 disabled:bg-blue-400",
secondary: "bg-gray-100 text-gray-900 hover:bg-gray-200",
ghost: "hover:bg-gray-100",
};
const sizes = {
sm: "h-8 px-3 text-sm gap-1.5",
md: "h-10 px-4 text-sm gap-2",
lg: "h-12 px-6 text-base gap-2.5",
};
return (
<button
ref={ref}
className={`${baseStyles} ${variants[variant]} ${sizes[size]} ${className}`}
disabled={disabled || loading}
{...props}
>
{loading ? (
<Spinner className="animate-spin" />
) : (
<>
{leftIcon}
{children}
{rightIcon}
</>
)}
</button>
);
}
);
Button.displayName = "Button";
```
## Generic Components
```typescript
// components/List.tsx
import { ReactNode } from "react";
interface ListProps<T> {
items: T[];
renderItem: (item: T, index: number) => ReactNode;
keyExtractor: (item: T, index: number) => string;
emptyState?: ReactNode;
loading?: boolean;
loadingComponent?: ReactNode;
}
export function List<T>({
items,
renderItem,
keyExtractor,
emptyState,
loading,
loadingComponent,
}: ListProps<T>) {
if (loading) {
return <>{loadingComponent || <DefaultLoader />}</>;
}
if (items.length === 0) {
return <>{emptyState || <DefaultEmpty />}</>;
}
return (
<ul className="space-y-2">
{items.map((item, index) => (
<li key={keyExtractor(item, index)}>{renderItem(item, index)}</li>
))}
</ul>
);
}
// Usage
interface User {
id: string;
name: string;
email: string;
}
<List<User>
items={users}
keyExtractor={(user) => user.id}
renderItem={(user) => (
<UserCard name={user.name} email={user.email} />
)}
emptyState={<p>No users found</p>}
/>
```
## Custom Hooks with TypeScript
```typescript
// hooks/useAsync.ts
import { useState, useCallback, useEffect } from "react";
interface AsyncState<T> {
data: T | null;
loading: boolean;
error: Error | null;
}
interface UseAsyncReturn<T, P extends unknown[]> extends AsyncState<T> {
execute: (...params: P) => Promise<T | null>;
reset: () => void;
}
export function useAsync<T, P extends unknown[] = []>(
asyncFunction: (...params: P) => Promise<T>,
immediate = false,
...immediateParams: P
): UseAsyncReturn<T, P> {
const [state, setState] = useState<AsyncState<T>>({
data: null,
loading: immediate,
error: null,
});
const execute = useCallback(
async (...params: P): Promise<T | null> => {
setState((prev) => ({ ...prev, loading: true, error: null }));
try {
const data = await asyncFunction(...params);
setState({ data, loading: false, error: null });
return data;
} catch (error) {
const err = error instanceof Error ? error : new Error(String(error));
setState({ data: null, loading: false, error: err });
return null;
}
},
[asyncFunction]
);
const reset = useCallback(() => {
setState({ data: null, loading: false, error: null });
}, []);
useEffect(() => {
if (immediate) {
execute(...immediateParams);
}
}, [immediate, execute]);
return { ...state, execute, reset };
}
// Usage
const { data: user, loading, error, execute: fetchUser } = useAsync(
(id: string) => api.getUser(id),
true,
userId
);
```
## Context with TypeScript
```typescript
// contexts/AuthContext.tsx
import { createContext, useContext, useState, useCallback, ReactNode } from "react";
interface User {
id: string;
email: string;
name: string;
role: "admin" | "user";
}
interface AuthContextValue {
user: User | null;
isAuthenticated: boolean;
login: (email: string, password: string) => Promise<void>;
logout: () => Promise<void>;
updateUser: (updates: Partial<User>) => void;
}
const AuthContext = createContext<AuthContextValue | null>(null);
export function AuthProvider({ children }: { children: ReactNode }) {
const [user, setUser] = useState<User | null>(null);
const login = useCallback(async (email: string, password: string) => {
const response = await api.login(email, password);
setUser(response.user);
}, []);
const logout = useCallback(async () => {
await api.logout();
setUser(null);
}, []);
const updateUser = useCallback((updates: Partial<User>) => {
setUser((prev) => (prev ? { ...prev, ...updates } : null));
}, []);
const value: AuthContextValue = {
user,
isAuthenticated: user !== null,
login,
logout,
updateUser,
};
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
}
export function useAuth(): AuthContextValue {
const context = useContext(AuthContext);
if (!context) {
throw new Error("useAuth must be used within AuthProvider");
}
return context;
}
```
## Event Handler Types
```typescript
// Properly typed event handlers
import { ChangeEvent, FormEvent, MouseEvent, KeyboardEvent } from "react";
function Form() {
const handleInputChange = (e: ChangeEvent<HTMLInputElement>) => {
console.log(e.target.value);
};
const handleSelectChange = (e: ChangeEvent<HTMLSelectElement>) => {
console.log(e.target.value);
};
const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
const formData = new FormData(e.currentTarget);
};
const handleClick = (e: MouseEvent<HTMLButtonElement>) => {
e.preventDefault();
};
const handleKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {
if (e.key === "Enter") {
e.preventDefault();
}
};
return (
<form onSubmit={handleSubmit}>
<input onChange={handleInputChange} onKeyDown={handleKeyDown} />
<select onChange={handleSelectChange} />
<button onClick={handleClick}>Submit</button>
</form>
);
}
```
## Best Practices
- Use strict TypeScript configuration
- Apply proper generic constraints
- Create typed context with null checks
- Use discriminated unions for state
- Implement proper event handler types
- Leverage type inference where possible
Google Antigravity IDE provides React TypeScript patterns and automatically infers component prop types for your applications.This React prompt is ideal for developers working on:
By using this prompt, you can save hours of manual coding and ensure best practices are followed from the start. It's particularly valuable for teams looking to maintain consistency across their react implementations.
Yes! All prompts on Antigravity AI Directory are free to use for both personal and commercial projects. No attribution required, though it's always appreciated.
This prompt works excellently with Claude, ChatGPT, Cursor, GitHub Copilot, and other modern AI coding assistants. For best results, use models with large context windows.
You can modify the prompt by adding specific requirements, constraints, or preferences. For React projects, consider mentioning your framework version, coding style, and any specific libraries you're using.