React Cheatsheet

Learn React with Hands-On Labs

Learn React frontend development through hands-on labs and real-world scenarios. LabEx provides comprehensive React courses covering essential component creation, state management, hooks, event handling, and performance optimization. Master building efficient and maintainable user interfaces for modern web applications.

Component Creation & JSX

Functional Components: function / =>

Create components using function syntax.

import React from 'react'

// Function declaration
function Welcome(props) {
  return <h1>Hello, {props.name}!</h1>
}

// Arrow function
const Welcome = (props) => {
  return <h1>Hello, {props.name}!</h1>
}

// Implicit return for simple components
const Greeting = ({ name }) => <h1>Hello, {name}!</h1>

Class Components: class extends React.Component

Create components using ES6 class syntax.

import React, { Component } from 'react'

class Welcome extends Component {
  render() {
    return <h1>Hello, {this.props.name}!</h1>
  }
}

// With constructor
class Counter extends Component {
  constructor(props) {
    super(props)
    this.state = { count: 0 }
  }
  render() {
    return <div>Count: {this.state.count}</div>
  }
}

JSX Elements: <element>

Write HTML-like syntax within JavaScript.

// JSX element
const element = <h1>Hello, world!</h1>

// JSX with expressions
const name = 'John'
const greeting = <h1>Hello, {name}!</h1>

// Multi-line JSX
const element = (
  <div>
    <h1>Welcome!</h1>
    <p>Good to see you here.</p>
  </div>
)

Component Export: export default / export

Export components for use in other files.

// Default export
export default function App() {
  return <div>My App</div>
}

// Named export
export const Button = () => <button>Click me</button>

Component Import: import

Import components from other files.

// Import default component
import App from './App'

// Import named component
import { Button } from './Button'

// Import multiple components
import React, { useState, useEffect } from 'react'

// Import with alias
import { Button as MyButton } from './Button'

Fragment: <React.Fragment> / <>

Group elements without adding extra DOM nodes.

// Using React.Fragment
return (
  <React.Fragment>
    <h1>Title</h1>
    <p>Description</p>
  </React.Fragment>
)

// Using short syntax
return (
  <>
    <h1>Title</h1>
    <p>Description</p>
  </>
)

Props & Component Structure

Props: props.name

Pass data from parent to child components.

// Receiving props
function Welcome(props) {
  return <h1>Hello, {props.name}!</h1>
}

// Destructuring props
function Welcome({ name, age }) {
  return (
    <h1>
      Hello, {name}! You are {age} years old.
    </h1>
  )
}

// Default props
function Welcome({ name = 'Guest' }) {
  return <h1>Hello, {name}!</h1>
}
Quiz

Sign in to answer this quiz and track your learning progress

How do you pass data from a parent component to a child component in React?
Using state variables
Using props
Using refs
Using context API

PropTypes: Component.propTypes

Validate props passed to components (requires prop-types package).

import PropTypes from 'prop-types'

function Welcome({ name, age }) {
  return (
    <h1>
      Hello, {name}! Age: {age}
    </h1>
  )
}

Welcome.propTypes = {
  name: PropTypes.string.isRequired,
  age: PropTypes.number,
}

Welcome.defaultProps = {
  age: 18,
}

Children: props.children

Access content passed between component opening/closing tags.

// Component that uses children
function Card({ children }) {
  return <div className="card">{children}</div>
}

// Usage
;<Card>
  <h2>Title</h2>
  <p>Content here</p>
</Card>

State Management & Hooks

useState Hook: useState()

Add state to functional components.

import React, { useState } from 'react'

function Counter() {
  const [count, setCount] = useState(0)
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  )
}

// Multiple state variables
function Form() {
  const [name, setName] = useState('')
  const [email, setEmail] = useState('')
}
Quiz

Sign in to answer this quiz and track your learning progress

What does useState(0) return?
An array with the state value and a function to update it
Just the state value
A function to update the state
Nothing, it just sets the state

useEffect Hook: useEffect()

Perform side effects in functional components.

import React, { useState, useEffect } from 'react'

function Timer() {
  const [count, setCount] = useState(0)

  // Effect runs after every render
  useEffect(() => {
    document.title = `Count: ${count}`
  })

  // Effect with cleanup
  useEffect(() => {
    const timer = setInterval(() => setCount((c) => c + 1), 1000)
    return () => clearInterval(timer)
  }, [])
}
Quiz

Sign in to answer this quiz and track your learning progress

What does the empty dependency array [] in useEffect(() => {...}, []) mean?
The effect runs on every render
The effect never runs
The effect runs twice
The effect runs only once after the initial render

Class State: this.state / setState()

Manage state in class components.

class Counter extends React.Component {
  constructor(props) {
    super(props)
    this.state = { count: 0 }
  }
  increment = () => {
    this.setState({ count: this.state.count + 1 })
  }
  render() {
    return (
      <div>
        <p>Count: {this.state.count}</p>
        <button onClick={this.increment}>Increment</button>
      </div>
    )
  }
}

Custom Hooks: use...

Create reusable stateful logic.

// Custom hook
function useCounter(initialValue = 0) {
  const [count, setCount] = useState(initialValue)
  const increment = () => setCount(count + 1)
  const decrement = () => setCount(count - 1)
  const reset = () => setCount(initialValue)
  return { count, increment, decrement, reset }
}

// Usage
function Counter() {
  const { count, increment, decrement, reset } = useCounter(0)
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>+</button>
      <button onClick={decrement}>-</button>
      <button onClick={reset}>Reset</button>
    </div>
  )
}

Event Handling

Quiz

Sign in to answer this quiz and track your learning progress

What is the purpose of PropTypes in React?
To validate the types of props passed to components
To improve component performance
To automatically style components
To make components faster

Click Events: onClick

Handle button clicks and element interactions.

function Button() {
  const handleClick = () => {
    alert('Button clicked!')
  }
  return <button onClick={handleClick}>Click me</button>
}

// Inline event handler
function Button() {
  return <button onClick={() => alert('Clicked!')}>Click me</button>
}

// Passing parameters
function Button() {
  const handleClick = (message) => {
    alert(message)
  }
  return <button onClick={() => handleClick('Hello!')}>Click me</button>
}

Form Events: onChange / onSubmit

Handle form inputs and submissions.

function Form() {
  const [value, setValue] = useState('')
  const handleChange = (e) => {
    setValue(e.target.value)
  }
  const handleSubmit = (e) => {
    e.preventDefault()
    console.log('Submitted:', value)
  }
  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        value={value}
        onChange={handleChange}
        placeholder="Enter text"
      />
      <button type="submit">Submit</button>
    </form>
  )
}

Event Object: event.target / event.preventDefault()

Access event properties and control default behavior.

function handleInput(event) {
  console.log('Input value:', event.target.value)
  console.log('Input name:', event.target.name)
}

function handleFormSubmit(event) {
  event.preventDefault() // Prevent form submission
  console.log('Form submitted')
}

// Event delegation
function List() {
  const handleClick = (event) => {
    if (event.target.tagName === 'BUTTON') {
      console.log('Button clicked:', event.target.textContent)
    }
  }
  return (
    <div onClick={handleClick}>
      <button>Button 1</button>
      <button>Button 2</button>
    </div>
  )
}

Keyboard Events: onKeyDown / onKeyUp

Respond to keyboard interactions.

function KeyboardHandler() {
  const handleKeyDown = (event) => {
    if (event.key === 'Enter') {
      console.log('Enter key pressed')
    }
    if (event.ctrlKey && event.key === 's') {
      event.preventDefault()
      console.log('Ctrl+S pressed')
    }
  }
  return <input onKeyDown={handleKeyDown} placeholder="Type here..." />
}

Conditional Rendering

Conditional Operators: && / ?:

Show/hide elements based on conditions.

function Greeting({ user }) {
  return (
    <div>
      {user && <h1>Welcome, {user.name}!</h1>}
      {!user && <h1>Please log in</h1>}
    </div>
  )
}

// Ternary operator
function Status({ isOnline }) {
  return <div>User is {isOnline ? 'online' : 'offline'}</div>
}

If/Else Logic: if statements

Use traditional JavaScript logic for complex conditions.

function UserProfile({ user, isAdmin }) {
  if (!user) {
    return <div>Loading...</div>
  }
  if (isAdmin) {
    return <AdminPanel user={user} />
  }
  return <UserPanel user={user} />
}

// Early return pattern
function Component({ data }) {
  if (!data) return null
  if (data.error) return <ErrorMessage />
  return <DataDisplay data={data} />
}

Switch Statements: switch

Handle multiple conditions efficiently.

function StatusIcon({ status }) {
  switch (status) {
    case 'loading':
      return <Spinner />
    case 'success':
      return <CheckIcon />
    case 'error':
      return <ErrorIcon />
    default:
      return null
  }
}

Dynamic Styles: Conditional CSS

Apply styles based on component state or props.

function Button({ variant, disabled }) {
  const className = `btn ${variant} ${disabled ? 'disabled' : ''}`
  return (
    <button
      className={className}
      style={{
        backgroundColor: variant === 'primary' ? 'blue' : 'gray',
        opacity: disabled ? 0.5 : 1,
      }}
      disabled={disabled}
    >
      Click me
    </button>
  )
}

List Rendering & Keys

Map Function: array.map()

Render lists of components from array data.

function TodoList({ todos }) {
  return (
    <ul>
      {todos.map((todo) => (
        <li key={todo.id}>{todo.text}</li>
      ))}
    </ul>
  )
}

// With index (avoid when possible)
function ItemList({ items }) {
  return (
    <ul>
      {items.map((item, index) => (
        <li key={index}>{item}</li>
      ))}
    </ul>
  )
}

Keys: key prop

Provide unique identifiers for list items to optimize rendering.

// Good: using unique ID
function UserList({ users }) {
  return (
    <ul>
      {users.map((user) => (
        <li key={user.id}>
          <UserCard user={user} />
        </li>
      ))}
    </ul>
  )
}

// Creating compound keys
function CommentList({ comments }) {
  return (
    <div>
      {comments.map((comment) => (
        <Comment key={`${comment.postId}-${comment.id}`} comment={comment} />
      ))}
    </div>
  )
}

Filter & Map: Array methods

Process arrays before rendering them.

function TaskList({ tasks, showCompleted }) {
  const filteredTasks = showCompleted
    ? tasks
    : tasks.filter((task) => !task.completed)
  return (
    <ul>
      {filteredTasks.map((task) => (
        <li key={task.id} className={task.completed ? 'completed' : ''}>
          {task.title}
        </li>
      ))}
    </ul>
  )
}

Empty States: Handling empty arrays

Display appropriate content when lists are empty.

function ProductList({ products }) {
  if (products.length === 0) {
    return <div>No products found.</div>
  }
  return (
    <div>
      {products.map((product) => (
        <ProductCard key={product.id} product={product} />
      ))}
    </div>
  )
}

Performance Optimization

React.memo: React.memo()

Prevent unnecessary re-renders of functional components.

const ExpensiveComponent = React.memo(function ExpensiveComponent({ data }) {
  return <div>{/* Complex rendering logic */}</div>
})

// With custom comparison
const MyComponent = React.memo(
  function MyComponent({ user }) {
    return <div>{user.name}</div>
  },
  (prevProps, nextProps) => {
    return prevProps.user.id === nextProps.user.id
  },
)

useMemo Hook: useMemo()

Memoize expensive calculations.

function ExpensiveList({ items, searchTerm }) {
  const filteredItems = useMemo(() => {
    return items.filter((item) =>
      item.name.toLowerCase().includes(searchTerm.toLowerCase()),
    )
  }, [items, searchTerm])
  return (
    <ul>
      {filteredItems.map((item) => (
        <li key={item.id}>{item.name}</li>
      ))}
    </ul>
  )
}

useCallback Hook: useCallback()

Memoize function references to prevent unnecessary re-renders.

function Parent({ items }) {
  const [count, setCount] = useState(0)
  const handleItemClick = useCallback((itemId) => {
    console.log('Item clicked:', itemId)
  }, []) // Empty dependency array
  return (
    <div>
      <button onClick={() => setCount(count + 1)}>Count: {count}</button>
      <ItemList items={items} onItemClick={handleItemClick} />
    </div>
  )
}

Lazy Loading: React.lazy() / Suspense

Load components only when needed to reduce bundle size.

const LazyComponent = React.lazy(() => import('./LazyComponent'))

function App() {
  return (
    <div>
      <Suspense fallback={<div>Loading...</div>}>
        <LazyComponent />
      </Suspense>
    </div>
  )
}

Component Communication

Props Down: Parent to Child

Pass data from parent components to child components.

function Parent() {
  const [user, setUser] = useState({ name: 'John', age: 30 })
  return (
    <div>
      <ChildComponent user={user} />
      <AnotherChild userName={user.name} />
    </div>
  )
}

function ChildComponent({ user }) {
  return <div>Hello, {user.name}!</div>
}

Callbacks Up: Child to Parent

Send data from child components back to parent components.

function Parent() {
  const [message, setMessage] = useState('')
  const handleChildMessage = (msg) => {
    setMessage(msg)
  }
  return (
    <div>
      <p>Message: {message}</p>
      <Child onMessage={handleChildMessage} />
    </div>
  )
}

function Child({ onMessage }) {
  return (
    <button onClick={() => onMessage('Hello from child!')}>Send Message</button>
  )
}

Context API: createContext / useContext

Share state across multiple components without prop drilling.

const UserContext = React.createContext()

function App() {
  const [user, setUser] = useState({ name: 'John' })
  return (
    <UserContext.Provider value={{ user, setUser }}>
      <Header />
      <Main />
    </UserContext.Provider>
  )
}

function Header() {
  const { user } = useContext(UserContext)
  return <h1>Welcome, {user.name}!</h1>
}

Refs: useRef / forwardRef

Access DOM elements or store mutable values.

function TextInput() {
  const inputRef = useRef(null)
  const focusInput = () => {
    inputRef.current.focus()
  }
  return (
    <div>
      <input ref={inputRef} type="text" />
      <button onClick={focusInput}>Focus Input</button>
    </div>
  )
}

// Forward refs
const FancyInput = forwardRef((props, ref) => (
  <input className="fancy" ref={ref} {...props} />
))

Development Tools & Debugging

React DevTools: Browser Extension

Debug React components and inspect component tree.

// Install React DevTools browser extension
// Components tab: Inspect component hierarchy
// Profiler tab: Measure performance

// Console debugging
function MyComponent(props) {
  console.log('MyComponent props:', props)
  console.log('MyComponent rendered')
  return <div>{props.children}</div>
}

Error Boundaries: componentDidCatch

Catch JavaScript errors in component tree and display fallback UI.

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props)
    this.state = { hasError: false }
  }
  static getDerivedStateFromError(error) {
    return { hasError: true }
  }
  componentDidCatch(error, errorInfo) {
    console.log('Error caught:', error, errorInfo)
  }
  render() {
    if (this.state.hasError) {
      return <h1>Something went wrong.</h1>
    }
    return this.props.children
  }
}

Strict Mode: React.StrictMode

Enable additional checks and warnings for development.

import React from 'react'
import ReactDOM from 'react-dom'

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root'),
)

Profiling: Performance measurement

Measure component performance and identify bottlenecks.

// Using React DevTools Profiler
// Wrap components to profile
import { Profiler } from 'react'

function onRenderCallback(id, phase, actualDuration) {
  console.log('Component', id, 'took', actualDuration, 'ms')
}

;<Profiler id="App" onRender={onRenderCallback}>
  <App />
</Profiler>

React Installation & Setup

Create React App: npx create-react-app

Quickly bootstrap a new React project.

# Create new React app
npx create-react-app my-app
cd my-app

# Start development server
npm start

# Build for production
npm run build

# Run tests
npm test

Vite: npm create vite@latest

Fast build tool and dev server for React projects.

# Create new Vite React app
npm create vite@latest my-react-app -- --template react
cd my-react-app
npm install

# Start development server
npm run dev

# Build for production
npm run build

Manual Setup / Import

Add React to existing project or use CDN.

# Install React and ReactDOM
npm install react react-dom

# For development
npm install --save-dev @vitejs/plugin-react
// Basic React import
import React from 'react'
import ReactDOM from 'react-dom/client'

// Render to DOM
const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(<App />)

Advanced Patterns & Features

Higher-Order Components (HOC)

Reuse component logic by wrapping components.

function withLoading(WrappedComponent) {
  return function WithLoadingComponent(props) {
    if (props.isLoading) {
      return <div>Loading...</div>
    }
    return <WrappedComponent {...props} />
  }
}

// Usage
const UserListWithLoading = withLoading(UserList)
;<UserListWithLoading users={users} isLoading={loading} />

Render Props Pattern

Share code between components using a prop whose value is a function.

function DataFetcher({ render, url }) {
  const [data, setData] = useState(null)
  const [loading, setLoading] = useState(true)
  useEffect(() => {
    fetch(url)
      .then((res) => res.json())
      .then((data) => {
        setData(data)
        setLoading(false)
      })
  }, [url])
  return render({ data, loading })
}

// Usage
;<DataFetcher
  url="/api/users"
  render={({ data, loading }) =>
    loading ? <Spinner /> : <UserList users={data} />
  }
/>

Compound Components

Create components that work together as a cohesive unit.

function Tabs({ children, activeTab }) {
  return (
    <div className="tabs">
      {React.Children.map(children, (child, index) =>
        React.cloneElement(child, { isActive: index === activeTab }),
      )}
    </div>
  )
}

function Tab({ children, isActive }) {
  return <div className={`tab ${isActive ? 'active' : ''}`}>{children}</div>
}

// Usage
;<Tabs activeTab={0}>
  <Tab>Tab 1 Content</Tab>
  <Tab>Tab 2 Content</Tab>
</Tabs>

Portal: ReactDOM.createPortal()

Render children into a DOM node outside the parent component’s hierarchy.

import ReactDOM from 'react-dom'

function Modal({ children, isOpen }) {
  if (!isOpen) return null
  return ReactDOM.createPortal(
    <div className="modal-overlay">
      <div className="modal">{children}</div>
    </div>,
    document.getElementById('modal-root'),
  )
}

Composition over Inheritance

Use composition patterns instead of extending classes.

// Good: Composition
function Button({ variant, children, ...props }) {
  return (
    <button className={`btn btn-${variant}`} {...props}>
      {children}
    </button>
  )
}

function IconButton({ icon, children, ...props }) {
  return (
    <Button {...props}>
      <Icon name={icon} />
      {children}
    </Button>
  )
}

Component Patterns: Flexible APIs

Design component APIs that are flexible and easy to use.

// Flexible Card component
function Card({ header, children, footer, variant = 'default' }) {
  return (
    <div className={`card card-${variant}`}>
      {header && <div className="card-header">{header}</div>}
      <div className="card-body">{children}</div>
      {footer && <div className="card-footer">{footer}</div>}
    </div>
  )
}

// Usage
;<Card header={<h3>Title</h3>} footer={<Button>Action</Button>}>
  Card content here
</Card>