Core Concepts
Components and Props
// Functional Component
function Welcome(props) {
return <h1>Hello, {props.name}</h1>
}
// Class Component
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>
}
}
// Props Example
const element = <Welcome name="John" />
State and Lifecycle
function Counter() {
const [count, setCount] = useState(0)
useEffect(() => {
document.title = `Count: ${count}`
return () => {
// cleanup
}
}, [count])
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
)
}
Hooks
// useState
function NameForm() {
const [name, setName] = useState('')
return <input value={name} onChange={(e) => setName(e.target.value)} />
}
// useEffect
function DataFetcher() {
const [data, setData] = useState(null)
useEffect(() => {
fetchData().then(setData)
}, [])
return data ? <div>{data}</div> : <div>Loading...</div>
}
// useContext
const ThemeContext = React.createContext('light')
function ThemedButton() {
const theme = useContext(ThemeContext)
return <button className={theme}>Themed Button</button>
}
// useReducer
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 }
case 'decrement':
return { count: state.count - 1 }
default:
throw new Error()
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, { count: 0 })
return (
<>
Count: {state.count}
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
</>
)
}
Event Handling
function ActionButton() {
const handleClick = (e) => {
e.preventDefault()
console.log('Button clicked')
}
return <button onClick={handleClick}>Click me</button>
}
Advanced Patterns
Context API
// Create context
const ThemeContext = React.createContext({
theme: 'light',
toggleTheme: () => {},
})
// Provider
function ThemeProvider({ children }) {
const [theme, setTheme] = useState('light')
const toggleTheme = () => {
setTheme(theme === 'light' ? 'dark' : 'light')
}
return <ThemeContext.Provider value={{ theme, toggleTheme }}>{children}</ThemeContext.Provider>
}
// Consumer
function ThemedComponent() {
const { theme, toggleTheme } = useContext(ThemeContext)
return (
<div className={theme}>
<button onClick={toggleTheme}>Toggle Theme</button>
</div>
)
}
Custom Hooks
// Custom Hook for form handling
function useForm(initialValues) {
const [values, setValues] = useState(initialValues)
const handleChange = (e) => {
const { name, value } = e.target
setValues((prev) => ({
...prev,
[name]: value,
}))
}
const resetForm = () => {
setValues(initialValues)
}
return [values, handleChange, resetForm]
}
// Usage
function SignupForm() {
const [values, handleChange, resetForm] = useForm({
username: '',
email: '',
password: '',
})
const handleSubmit = (e) => {
e.preventDefault()
console.log(values)
resetForm()
}
return (
<form onSubmit={handleSubmit}>
<input name="username" value={values.username} onChange={handleChange} />
{/* Other fields */}
</form>
)
}
HOC (Higher Order Components)
// HOC Example
function withSubscription(WrappedComponent, selectData) {
return function (props) {
const [data, setData] = useState(null)
useEffect(() => {
const subscription = DataSource.subscribe((data) => {
setData(selectData(data, props))
})
return () => subscription.unsubscribe()
}, [props])
return <WrappedComponent data={data} {...props} />
}
}
// Usage
const CommentListWithSubscription = withSubscription(CommentList, (DataSource, props) =>
DataSource.getComments()
)
Render Props
class Mouse extends React.Component {
state = { x: 0, y: 0 }
handleMouseMove = (event) => {
this.setState({
x: event.clientX,
y: event.clientY,
})
}
render() {
return <div onMouseMove={this.handleMouseMove}>{this.props.render(this.state)}</div>
}
}
// Usage
;<Mouse
render={({ x, y }) => (
<h1>
Mouse position: {x}, {y}
</h1>
)}
/>
Performance Optimization
React.memo
const MemoizedComponent = React.memo(function MyComponent(props) {
return <div>{props.name}</div>
})
useMemo and useCallback
function ExpensiveComponent({ data, onItemSelect }) {
// Memoize expensive calculations
const processedData = useMemo(() => {
return expensiveOperation(data)
}, [data])
// Memoize callbacks
const handleSelect = useCallback(
(item) => {
onItemSelect(item.id)
},
[onItemSelect]
)
return (
<div>
{processedData.map((item) => (
<Item key={item.id} item={item} onSelect={handleSelect} />
))}
</div>
)
}
Code Splitting
// Dynamic Import
const OtherComponent = React.lazy(() => import('./OtherComponent'))
function MyComponent() {
return (
<Suspense fallback={<div>Loading...</div>}>
<OtherComponent />
</Suspense>
)
}
State Management
Redux Integration
// Actions
const increment = () => ({
type: 'INCREMENT',
})
// Reducer
function counterReducer(state = 0, action) {
switch (action.type) {
case 'INCREMENT':
return state + 1
default:
return state
}
}
// Component
function Counter({ count, increment }) {
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>Increment</button>
</div>
)
}
// Connect to Redux
export default connect((state) => ({ count: state }), { increment })(Counter)
Zustand Example
import create from 'zustand'
const useStore = create((set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
decrement: () => set((state) => ({ count: state.count - 1 })),
}))
function Counter() {
const { count, increment } = useStore()
return <button onClick={increment}>Count: {count}</button>
}
Testing
// Component Test
import { render, fireEvent } from '@testing-library/react'
test('increments counter', () => {
const { getByText } = render(<Counter />)
const button = getByText(/increment/i)
fireEvent.click(button)
expect(getByText(/count: 1/i)).toBeInTheDocument()
})
// Hook Test
import { renderHook, act } from '@testing-library/react-hooks'
test('useCounter', () => {
const { result } = renderHook(() => useCounter())
act(() => {
result.current.increment()
})
expect(result.current.count).toBe(1)
})
Error Handling
class ErrorBoundary extends React.Component {
state = { hasError: false }
static getDerivedStateFromError(error) {
return { hasError: true }
}
componentDidCatch(error, errorInfo) {
logErrorToService(error, errorInfo)
}
render() {
if (this.state.hasError) {
return <h1>Something went wrong.</h1>
}
return this.props.children
}
}
// Usage
;<ErrorBoundary>
<MyComponent />
</ErrorBoundary>
Routing
import { BrowserRouter, Routes, Route, Link } from 'react-router-dom'
function App() {
return (
<BrowserRouter>
<nav>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
</nav>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/users/:id" element={<UserProfile />} />
<Route path="*" element={<NotFound />} />
</Routes>
</BrowserRouter>
)
}
Resources
Official Documentation
Learning Resources
Tools
Popular Libraries