React Commands
React is a JavaScript library for building user interfaces with reusable components.
Project Setup
Create React App
# Using Create React App
npx create-react-app my-app
cd my-app
npm start
# With TypeScript
npx create-react-app my-app --template typescript
# With custom template
npx create-react-app my-app --template cra-template-typescript
Vite (Recommended for New Projects)
# Create Vite project
npm create vite@latest my-app -- --template react
# With TypeScript
npm create vite@latest my-app -- --template react-ts
# Install and run
cd my-app
npm install
npm run dev
Development Commands
| Command | Description |
|---|---|
npm start | Start development server |
npm run dev | Start Vite dev server |
npm test | Run tests |
npm run build | Build for production |
npm run lint | Run ESLint |
npm run preview | Preview production build |
React Hooks
useState
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
useEffect
import { useEffect, useState } from 'react';
function DataFetcher() {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch('/api/data')
.then(res => res.json())
.then(data => {
setData(data);
setLoading(false);
});
}, []); // Dependency array
return loading ? <p>Loading...</p> : <div>{JSON.stringify(data)}</div>;
}
useContext
import { createContext, useContext } from 'react';
const ThemeContext = createContext();
export function useTheme() {
return useContext(ThemeContext);
}
function App() {
return (
<ThemeContext.Provider value="dark">
<Header />
</ThemeContext.Provider>
);
}
function Header() {
const theme = useTheme();
return <h1>Theme: {theme}</h1>;
}
useReducer
import { useReducer } from 'react';
interface State {
count: number;
}
type Action = { type: 'INCREMENT' } | { type: 'DECREMENT' };
function reducer(state: State, action: Action): State {
switch (action.type) {
case 'INCREMENT':
return { count: state.count + 1 };
case 'DECREMENT':
return { count: state.count - 1 };
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, { count: 0 });
return (
<div>
<p>{state.count}</p>
<button onClick={() => dispatch({ type: 'INCREMENT' })}>+</button>
<button onClick={() => dispatch({ type: 'DECREMENT' })}>-</button>
</div>
);
}
useRef
import { useRef } from 'react';
function TextInput() {
const inputRef = useRef<HTMLInputElement>(null);
const handleClick = () => {
inputRef.current?.focus();
};
return (
<>
<input ref={inputRef} />
<button onClick={handleClick}>Focus Input</button>
</>
);
}
useMemo & useCallback
import { useMemo, useCallback } from 'react';
function Parent() {
const [count, setCount] = useState(0);
// Memoized value
const expensiveValue = useMemo(() => {
return count * 2;
}, [count]);
// Memoized callback
const handleClick = useCallback(() => {
setCount(c => c + 1);
}, []);
return <Child value={expensiveValue} onClick={handleClick} />;
}
Custom Hooks
function useFetch(url: string) {
const [data, setData] = useState(null);
const [error, setError] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch(url)
.then(res => res.json())
.then(data => {
setData(data);
setLoading(false);
})
.catch(err => {
setError(err);
setLoading(false);
});
}, [url]);
return { data, error, loading };
}
// Usage
function App() {
const { data, error, loading } = useFetch('/api/users');
return loading ? <p>Loading...</p> : <div>{JSON.stringify(data)}</div>;
}
Component Patterns
Functional Component
interface Props {
name: string;
age: number;
onClick?: (name: string) => void;
}
function User({ name, age, onClick }: Props) {
return (
<div onClick={() => onClick?.(name)}>
<h2>{name}</h2>
<p>Age: {age}</p>
</div>
);
}
export default User;
Controlled Component
function Form() {
const [formData, setFormData] = useState({
name: '',
email: '',
message: ''
});
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
const { name, value } = e.target;
setFormData(prev => ({
...prev,
[name]: value
}));
};
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
console.log(formData);
};
return (
<form onSubmit={handleSubmit}>
<input name="name" value={formData.name} onChange={handleChange} />
<input name="email" value={formData.email} onChange={handleChange} />
<textarea name="message" value={formData.message} onChange={handleChange} />
<button type="submit">Submit</button>
</form>
);
}
List Rendering
interface Item {
id: number;
name: string;
}
function ItemList({ items }: { items: Item[] }) {
return (
<ul>
{items.map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
);
}
Conditional Rendering
function Alert({ type, message }: { type: 'error' | 'success'; message: string }) {
if (!message) return null;
const className = type === 'error' ? 'alert-error' : 'alert-success';
return (
<div className={className}>
{message}
</div>
);
}
// Using ternary
function Status({ isActive }: { isActive: boolean }) {
return isActive ? <p>Active</p> : <p>Inactive</p>;
}
// Using &&
function Message({ count }: { count: number }) {
return count > 0 && <p>You have {count} messages</p>;
}
State Management
Context API
interface AppContextType {
user: User | null;
setUser: (user: User) => void;
}
const AppContext = createContext<AppContextType | undefined>(undefined);
export function useAppContext() {
const context = useContext(AppContext);
if (!context) {
throw new Error('useAppContext must be used within AppProvider');
}
return context;
}
export function AppProvider({ children }: { children: React.ReactNode }) {
const [user, setUser] = useState<User | null>(null);
return (
<AppContext.Provider value={{ user, setUser }}>
{children}
</AppContext.Provider>
);
}
Forms with React Hook Form
import { useForm } from 'react-hook-form';
interface FormData {
name: string;
email: string;
}
function MyForm() {
const { register, handleSubmit, formState: { errors } } = useForm<FormData>();
const onSubmit = (data: FormData) => {
console.log(data);
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register('name', { required: 'Name is required' })} />
{errors.name && <span>{errors.name.message}</span>}
<input {...register('email', { required: 'Email is required' })} />
{errors.email && <span>{errors.email.message}</span>}
<button type="submit">Submit</button>
</form>
);
}
Styling
Inline Styles
const styles = {
container: {
padding: '20px',
backgroundColor: '#f0f0f0'
},
title: {
fontSize: '24px',
color: '#333'
}
};
function App() {
return (
<div style={styles.container}>
<h1 style={styles.title}>Hello</h1>
</div>
);
}
CSS Modules
// App.module.css
.container {
padding: 20px;
background-color: #f0f0f0;
}
// App.tsx
import styles from './App.module.css';
function App() {
return <div className={styles.container}>Hello</div>;
}
Tailwind CSS
function App() {
return (
<div className="flex items-center justify-center min-h-screen bg-gray-100">
<div className="bg-white p-8 rounded-lg shadow-lg">
<h1 className="text-3xl font-bold text-gray-800">Hello</h1>
</div>
</div>
);
}
Testing
Unit Tests with Jest & React Testing Library
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import App from './App';
describe('App', () => {
test('renders heading', () => {
render(<App />);
expect(screen.getByText(/hello/i)).toBeInTheDocument();
});
test('increments counter on button click', async () => {
render(<Counter />);
const button = screen.getByRole('button', { name: /increment/i });
await userEvent.click(button);
expect(screen.getByText('1')).toBeInTheDocument();
});
});
Performance Optimization
React.memo
interface ItemProps {
name: string;
}
const Item = React.memo(({ name }: ItemProps) => {
console.log('Item rendered:', name);
return <div>{name}</div>;
});
Code Splitting with Suspense
import { Suspense, lazy } from 'react';
const Dashboard = lazy(() => import('./pages/Dashboard'));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<Dashboard />
</Suspense>
);
}
Common Patterns
Error Boundary
class ErrorBoundary extends React.Component<
{ children: React.ReactNode },
{ hasError: boolean }
> {
constructor(props: any) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error: Error) {
return { hasError: true };
}
render() {
if (this.state.hasError) {
return <h1>Something went wrong</h1>;
}
return this.props.children;
}
}
Portal
import { createPortal } from 'react-dom';
function Modal({ children }: { children: React.ReactNode }) {
return createPortal(
<div className="modal">{children}</div>,
document.getElementById('modal-root')!
);
}
Best Practices
- Use functional components and hooks
- Keep components small and focused
- Lift state up only when necessary
- Use composition over inheritance
- Implement proper error handling
- Use TypeScript for type safety
- Memoize expensive computations
- Lazy load routes and code
- Test components thoroughly
- Follow naming conventions
Useful Libraries
- React Query: Data fetching and caching
- Redux: State management
- React Router: Client-side routing
- Next.js: Full-stack framework
- Material-UI: Component library
- Styled Components: CSS-in-JS
Resources
Last updated: 2026-03-30|React 18+