React Cheat Sheet

Use this React cheat sheet as a quick reference for components, JSX, props, state, events, lists, forms, effects, refs, context, hooks, routing patterns, and common mistakes.

Basic React Component

A React component is a JavaScript function that returns UI.

function Welcome() {
    return <h1>Hello, React</h1>;
}

export default Welcome;

Use the component inside another component:

function App() {
    return (
        <main>
            <Welcome />
        </main>
    );
}

Component Basics

  • Component names must start with a capital letter.
  • Components return JSX.
  • JSX looks like HTML but follows JavaScript rules.
  • Components can receive data through props.
  • Components can manage local data with state.

JSX Basics

JSX lets you write UI inside JavaScript.

function App() {
    return (
        <section>
            <h1>My App</h1>
            <p>Welcome to the page.</p>
        </section>
    );
}

JSX Rules

  • Return one parent element.
  • Use className instead of class.
  • Use htmlFor instead of for.
  • Close every tag.
  • Wrap JavaScript expressions in curly braces.
  • Use camelCase for most DOM attributes.

Return One Parent Element

React components must return one parent element.

function Profile() {
    return (
        <div>
            <h1>Alex</h1>
            <p>Frontend Developer</p>
        </div>
    );
}

You can also use a fragment when you do not want an extra element.

function Profile() {
    return (
        <>
            <h1>Alex</h1>
            <p>Frontend Developer</p>
        </>
    );
}

JavaScript in JSX

Use curly braces to add JavaScript expressions inside JSX.

function UserGreeting() {
    const name = "Alex";

    return <h1>Hello, {name}</h1>;
}

Use expressions, not statements.

function Price() {
    const price = 20;
    const quantity = 3;

    return <p>Total: {price * quantity}</p>;
}

This works because price * quantity returns a value.

Attributes in JSX

Class Name

function Button() {
    return <button className="primary-button">Click me</button>;
}

Inline Styles

function Card() {
    return (
        <article style={{ padding: "24px", borderRadius: "12px" }}>
            Card content
        </article>
    );
}

Inline styles use an object. CSS property names use camelCase.

Labels

function EmailField() {
    return (
        <label htmlFor="email">
            Email
            <input id="email" type="email" />
        </label>
    );
}

Use htmlFor because for is a reserved word in JavaScript.

Props

Props pass data from a parent component to a child component.

function UserCard(props) {
    return <h2>{props.name}</h2>;
}

function App() {
    return <UserCard name="Alex" />;
}

Destructure Props

function UserCard({ name, role }) {
    return (
        <article>
            <h2>{name}</h2>
            <p>{role}</p>
        </article>
    );
}

Default Prop Value

function Avatar({ name = "Guest" }) {
    return <p>{name}</p>;
}

Pass Numbers and Booleans

function Product({ title, price, inStock }) {
    return (
        <article>
            <h2>{title}</h2>
            <p>${price}</p>
            <p>{inStock ? "In stock" : "Out of stock"}</p>
        </article>
    );
}

function App() {
    return <Product title="Course" price={29} inStock={true} />;
}

Use curly braces for non-string values.

Children

Use children when a component should wrap other content.

function Card({ children }) {
    return <article className="card">{children}</article>;
}

function App() {
    return (
        <Card>
            <h2>React Basics</h2>
            <p>Learn components, props, and state.</p>
        </Card>
    );
}

children helps you create reusable layout components.

State with useState

Use state for values that change and should update the UI.

import { useState } from "react";

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

    return (
        <button onClick={() => setCount(count + 1)}>
            Count: {count}
        </button>
    );
}

State Basics

  • count is the current value.
  • setCount updates the value.
  • useState(0) sets the initial value.
  • Updating state re-renders the component.

Update State Based on Previous State

Use the callback form when the next state depends on the previous state.

import { useState } from "react";

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

    function increase() {
        setCount((previousCount) => previousCount + 1);
    }

    return <button onClick={increase}>Count: {count}</button>;
}

This is safer when state updates may happen close together.

State with Objects

import { useState } from "react";

function ProfileForm() {
    const [user, setUser] = useState({
        name: "Alex",
        email: "alex@example.com"
    });

    function updateName() {
        setUser({
            ...user,
            name: "Sam"
        });
    }

    return (
        <>
            <p>{user.name}</p>
            <button onClick={updateName}>Change name</button>
        </>
    );
}

Do not mutate state directly. Create a new object with the changed value.

State with Arrays

import { useState } from "react";

function TodoList() {
    const [todos, setTodos] = useState(["Learn React"]);

    function addTodo() {
        setTodos([...todos, "Build a project"]);
    }

    return (
        <ul>
            {todos.map((todo) => (
                <li key={todo}>{todo}</li>
            ))}
        </ul>
    );
}

Use methods like map, filter, and spread syntax to create new arrays.

Events

React events use camelCase names.

function Button() {
    function handleClick() {
        console.log("Clicked");
    }

    return <button onClick={handleClick}>Click me</button>;
}

Inline Event Handler

function Button() {
    return (
        <button onClick={() => console.log("Clicked")}>
            Click me
        </button>
    );
}

Event Object

function SearchInput() {
    function handleChange(event) {
        console.log(event.target.value);
    }

    return <input type="text" onChange={handleChange} />;
}

Common event props include:

  • onClick
  • onChange
  • onSubmit
  • onFocus
  • onBlur
  • onKeyDown

Conditional Rendering

Use if

function Greeting({ isLoggedIn }) {
    if (isLoggedIn) {
        return <h1>Welcome back</h1>;
    }

    return <h1>Please log in</h1>;
}

Use a Ternary

function Greeting({ isLoggedIn }) {
    return (
        <h1>{isLoggedIn ? "Welcome back" : "Please log in"}</h1>
    );
}

Use &&

function Alert({ message }) {
    return (
        <div>
            {message && <p className="alert">{message}</p>}
        </div>
    );
}

Use && when you only want to show something if a value exists.

Render Lists

Use map() to render lists.

function CourseList() {
    const courses = ["HTML", "CSS", "React"];

    return (
        <ul>
            {courses.map((course) => (
                <li key={course}>{course}</li>
            ))}
        </ul>
    );
}

List of Objects

function ProductList() {
    const products = [
        { id: 1, name: "HTML Course" },
        { id: 2, name: "CSS Course" },
        { id: 3, name: "React Course" }
    ];

    return (
        <ul>
            {products.map((product) => (
                <li key={product.id}>{product.name}</li>
            ))}
        </ul>
    );
}

Key Rules

  • Add a key prop to each rendered item.
  • Use stable IDs when possible.
  • Avoid array indexes as keys when items can be reordered, added, or removed.

Forms

Controlled Input

import { useState } from "react";

function NameForm() {
    const [name, setName] = useState("");

    return (
        <input
            value={name}
            onChange={(event) => setName(event.target.value)}
            placeholder="Your name"
        />
    );
}

A controlled input stores its value in React state.

Submit a Form

import { useState } from "react";

function SignupForm() {
    const [email, setEmail] = useState("");

    function handleSubmit(event) {
        event.preventDefault();
        console.log(email);
    }

    return (
        <form onSubmit={handleSubmit}>
            <input
                type="email"
                value={email}
                onChange={(event) => setEmail(event.target.value)}
            />

            <button type="submit">Sign up</button>
        </form>
    );
}

Use event.preventDefault() when you want React to handle the form instead of the browser reloading the page.

useEffect

Use useEffect to run code after rendering.

import { useEffect } from "react";

function PageTitle() {
    useEffect(() => {
        document.title = "React App";
    }, []);

    return <h1>Home</h1>;
}

Effect with a Dependency

import { useEffect } from "react";

function SearchResults({ query }) {
    useEffect(() => {
        console.log(`Search changed: ${query}`);
    }, [query]);

    return <p>Results for {query}</p>;
}

The effect runs when query changes.

Cleanup Function

import { useEffect } from "react";

function Timer() {
    useEffect(() => {
        const intervalId = setInterval(() => {
            console.log("Tick");
        }, 1000);

        return () => {
            clearInterval(intervalId);
        };
    }, []);

    return <p>Timer running</p>;
}

Use cleanup for timers, subscriptions, and event listeners.

Fetch Data with useEffect

import { useEffect, useState } from "react";

function Users() {
    const [users, setUsers] = useState([]);
    const [isLoading, setIsLoading] = useState(true);

    useEffect(() => {
        async function loadUsers() {
            const response = await fetch("https://jsonplaceholder.typicode.com/users");
            const data = await response.json();

            setUsers(data);
            setIsLoading(false);
        }

        loadUsers();
    }, []);

    if (isLoading) {
        return <p>Loading...</p>;
    }

    return (
        <ul>
            {users.map((user) => (
                <li key={user.id}>{user.name}</li>
            ))}
        </ul>
    );
}

For larger apps, use a framework or data-fetching library when you need caching, loading states, and server rendering.

useRef

Use useRef to store a value that does not trigger a re-render, or to access a DOM element.

Focus an Input

import { useRef } from "react";

function SearchBox() {
    const inputRef = useRef(null);

    function focusInput() {
        inputRef.current.focus();
    }

    return (
        <>
            <input ref={inputRef} type="text" />
            <button onClick={focusInput}>Focus</button>
        </>
    );
}

Store a Mutable Value

import { useRef } from "react";

function ClickTracker() {
    const clickCount = useRef(0);

    function handleClick() {
        clickCount.current += 1;
        console.log(clickCount.current);
    }

    return <button onClick={handleClick}>Track clicks</button>;
}

Changing a ref does not re-render the component.

useMemo

Use useMemo to avoid recalculating an expensive value unless its dependencies change.

import { useMemo } from "react";

function ProductList({ products, search }) {
    const filteredProducts = useMemo(() => {
        return products.filter((product) =>
            product.name.toLowerCase().includes(search.toLowerCase())
        );
    }, [products, search]);

    return (
        <ul>
            {filteredProducts.map((product) => (
                <li key={product.id}>{product.name}</li>
            ))}
        </ul>
    );
}

Use useMemo when a calculation is actually expensive or causes avoidable work.

useCallback

Use useCallback to keep a function reference stable between renders.

import { useCallback, useState } from "react";

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

    const increase = useCallback(() => {
        setCount((previousCount) => previousCount + 1);
    }, []);

    return <button onClick={increase}>Count: {count}</button>;
}

Use this mainly when passing callbacks to memoized child components.

React.memo

Use memo to skip re-rendering a component when its props have not changed.

import { memo } from "react";

const UserCard = memo(function UserCard({ name }) {
    return <p>{name}</p>;
});

export default UserCard;

Use it for components that render often with the same props. Avoid adding it everywhere by default.

Context

Context passes data through the component tree without manually passing props at every level.

import { createContext, useContext } from "react";

const ThemeContext = createContext("light");

function ThemeLabel() {
    const theme = useContext(ThemeContext);

    return <p>Current theme: {theme}</p>;
}

function App() {
    return (
        <ThemeContext.Provider value="dark">
            <ThemeLabel />
        </ThemeContext.Provider>
    );
}

Use context for shared values such as theme, current user, locale, or feature settings.

Custom Hooks

A custom hook is a reusable function that uses React hooks.

import { useEffect, useState } from "react";

function useWindowWidth() {
    const [width, setWidth] = useState(window.innerWidth);

    useEffect(() => {
        function handleResize() {
            setWidth(window.innerWidth);
        }

        window.addEventListener("resize", handleResize);

        return () => {
            window.removeEventListener("resize", handleResize);
        };
    }, []);

    return width;
}

function LayoutInfo() {
    const width = useWindowWidth();

    return <p>Window width: {width}</p>;
}

Custom hook names must start with use.

Rules of Hooks

Follow these rules when using hooks:

  • Call hooks only at the top level of a component or custom hook.
  • Do not call hooks inside loops, conditions, or nested functions.
  • Call hooks only from React functions.
  • Keep dependency arrays accurate.
  • Use custom hooks to reuse hook logic.

Wrong:

function Profile({ isLoggedIn }) {
    if (isLoggedIn) {
        const [name, setName] = useState("Alex");
    }

    return <p>Profile</p>;
}

Better:

function Profile({ isLoggedIn }) {
    const [name, setName] = useState("Alex");

    if (!isLoggedIn) {
        return <p>Please log in</p>;
    }

    return <p>{name}</p>;
}

Styling in React

CSS Class

function Button() {
    return <button className="button">Click me</button>;
}
.button {
    padding: 12px 20px;
    border-radius: 8px;
}

Conditional Class

function Button({ isActive }) {
    return (
        <button className={isActive ? "button active" : "button"}>
            Save
        </button>
    );
}

Inline Style

function Alert() {
    return (
        <p style={{ color: "red", fontWeight: "bold" }}>
            Something went wrong
        </p>
    );
}

Use CSS classes for most styling. Use inline styles for dynamic values or small one-off styles.

React Router Pattern

React itself does not include routing. Many apps use a router library.

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 />} />
            </Routes>
        </BrowserRouter>
    );
}

Use your framework’s routing system if you work with Next.js, Remix, or another React framework.

Code Splitting with lazy

Use lazy to load a component only when needed.

import { lazy, Suspense } from "react";

const SettingsPage = lazy(() => import("./SettingsPage"));

function App() {
    return (
        <Suspense fallback={<p>Loading...</p>}>
            <SettingsPage />
        </Suspense>
    );
}

This can reduce the initial JavaScript loaded by the page.

Error Boundaries

Error boundaries catch rendering errors in child components.

import { Component } from "react";

class ErrorBoundary extends Component {
    constructor(props) {
        super(props);

        this.state = {
            hasError: false
        };
    }

    static getDerivedStateFromError() {
        return {
            hasError: true
        };
    }

    render() {
        if (this.state.hasError) {
            return <p>Something went wrong.</p>;
        }

        return this.props.children;
    }
}

Use it like this:

function App() {
    return (
        <ErrorBoundary>
            <Dashboard />
        </ErrorBoundary>
    );
}

Error boundaries do not catch every type of error, but they help prevent a full UI crash from render errors.

Server Components

Some React frameworks support Server Components.

export default async function ProductsPage() {
    const response = await fetch("https://example.com/api/products");
    const products = await response.json();

    return (
        <ul>
            {products.map((product) => (
                <li key={product.id}>{product.name}</li>
            ))}
        </ul>
    );
}

Use Server Components for data fetching and read-only UI. Use Client Components for state, effects, event handlers, and browser APIs.

In Next.js App Router, add "use client" at the top when a component needs client-side behavior.

"use client";

import { useState } from "react";

function LikeButton() {
    const [likes, setLikes] = useState(0);

    return (
        <button onClick={() => setLikes(likes + 1)}>
            Likes: {likes}
        </button>
    );
}

Common React Patterns

Toggle UI

import { useState } from "react";

function TogglePanel() {
    const [isOpen, setIsOpen] = useState(false);

    return (
        <section>
            <button onClick={() => setIsOpen(!isOpen)}>
                Toggle
            </button>

            {isOpen && <p>Panel content</p>}
        </section>
    );
}

Filter a List

import { useState } from "react";

function CourseSearch() {
    const [search, setSearch] = useState("");

    const courses = ["HTML", "CSS", "JavaScript", "React"];

    const filteredCourses = courses.filter((course) =>
        course.toLowerCase().includes(search.toLowerCase())
    );

    return (
        <>
            <input
                value={search}
                onChange={(event) => setSearch(event.target.value)}
                placeholder="Search courses"
            />

            <ul>
                {filteredCourses.map((course) => (
                    <li key={course}>{course}</li>
                ))}
            </ul>
        </>
    );
}

Add an Item

import { useState } from "react";

function TodoApp() {
    const [todos, setTodos] = useState([]);
    const [text, setText] = useState("");

    function addTodo(event) {
        event.preventDefault();

        if (!text.trim()) {
            return;
        }

        setTodos([...todos, text]);
        setText("");
    }

    return (
        <form onSubmit={addTodo}>
            <input
                value={text}
                onChange={(event) => setText(event.target.value)}
            />

            <button type="submit">Add</button>

            <ul>
                {todos.map((todo) => (
                    <li key={todo}>{todo}</li>
                ))}
            </ul>
        </form>
    );
}

Remove an Item

import { useState } from "react";

function TodoList() {
    const [todos, setTodos] = useState([
        { id: 1, text: "Learn React" },
        { id: 2, text: "Build a project" }
    ]);

    function removeTodo(id) {
        setTodos(todos.filter((todo) => todo.id !== id));
    }

    return (
        <ul>
            {todos.map((todo) => (
                <li key={todo.id}>
                    {todo.text}
                    <button onClick={() => removeTodo(todo.id)}>
                        Remove
                    </button>
                </li>
            ))}
        </ul>
    );
}

Common Mistakes

Mutating State Directly

const [user, setUser] = useState({ name: "Alex" });

user.name = "Sam";
setUser(user);

Better:

setUser({
    ...user,
    name: "Sam"
});

Create a new object or array when updating state.

Missing Keys in Lists

{courses.map((course) => (
    <li>{course}</li>
))}

Better:

{courses.map((course) => (
    <li key={course}>{course}</li>
))}

Keys help React track list items.

Calling a Function Instead of Passing It

<button onClick={handleClick()}>Click me</button>

Better:

<button onClick={handleClick}>Click me</button>

Use an arrow function when you need to pass an argument.

<button onClick={() => handleDelete(id)}>Delete</button>

Using class Instead of className

<div class="card">Content</div>

Better:

<div className="card">Content</div>

JSX uses className.

Forgetting to Clean Up Effects

useEffect(() => {
    window.addEventListener("resize", handleResize);
}, []);

Better:

useEffect(() => {
    window.addEventListener("resize", handleResize);

    return () => {
        window.removeEventListener("resize", handleResize);
    };
}, []);

Clean up event listeners, timers, and subscriptions.

Using State for Values That Can Be Derived

const [fullName, setFullName] = useState(`${firstName} ${lastName}`);

Better:

const fullName = `${firstName} ${lastName}`;

Store state only when the value needs to change independently.

Debugging Tips

Log Props and State

function UserCard({ user }) {
    console.log(user);

    return <h2>{user.name}</h2>;
}

Use React Developer Tools

Use React Developer Tools to inspect:

  • Component tree
  • Props
  • State
  • Hooks
  • Context values
  • Render performance with the Profiler

Check the Browser Console

React errors often tell you:

  • Which component failed
  • Which prop or value caused the issue
  • Which hook rule was broken
  • Which list needs a key

Isolate the Component

Move the failing component into a smaller example with hardcoded props.

function TestPage() {
    return <UserCard user={{ name: "Alex" }} />;
}

This helps you find whether the bug comes from the component or the data passed into it.

Quick Reference

Create a Component

function App() {
    return <h1>Hello</h1>;
}

Use Props

function Greeting({ name }) {
    return <p>Hello, {name}</p>;
}

Use State

const [count, setCount] = useState(0);

Handle Clicks

<button onClick={handleClick}>Click</button>

Render a List

{items.map((item) => (
    <li key={item.id}>{item.name}</li>
))}

Render Conditionally

{isLoggedIn ? <Dashboard /> : <Login />}

Run an Effect

useEffect(() => {
    document.title = "React App";
}, []);

Use a Ref

const inputRef = useRef(null);

Use Context

const value = useContext(MyContext);

Create a Custom Hook

function useToggle(initialValue = false) {
    const [value, setValue] = useState(initialValue);

    function toggle() {
        setValue((currentValue) => !currentValue);
    }

    return [value, toggle];
}

Export a Component

export default App;

Import a Component

import App from "./App";