React Tutorial 0/120 lessons ~6 min read Lesson 39

    Hook Rules

    Rules of Hooks explain why Hooks must be called at the top level of React functions, how call order works, and common conditional or nested call mistakes.

    Course progress0%
    Focus
    38 guided sections
    Practice signal
    Examples included
    Career prep
    Interview Q&A included

    React Hooks provide a powerful way to use state, Effects, refs, and other React features inside function components.

    With that power comes an important requirement:

    Hooks must be called according to a consistent set of rules.

    These rules allow React to correctly preserve Hook state and behavior between renders.

    The two fundamental Rules of Hooks are:

    1. Only call Hooks at the top level.
    2. Only call Hooks from React function components or Custom Hooks.

    Understanding these rules is essential before building larger React applications.

    Why Do Rules of Hooks Exist?

    Consider:

    javascript
    const [count, setCount] = useState(0);
    const [name, setName] = useState("");

    React needs to associate each Hook call with the correct piece of state.

    Conceptually:

    text
    First useState → count
    Second useState → name

    React relies on the order of Hook calls remaining consistent between renders.

    If Hook calls are conditional, their order can change.

    For example:

    javascript
    if (isLoggedIn) {
    useState("user");
    }

    On one render, the Hook may be called.

    On another render, it may not.

    That makes the Hook ordering inconsistent.

    The Rules of Hooks prevent this problem.

    Rule 1: Only Call Hooks at the Top Level

    Hooks should be called at the top level of a React component or Custom Hook.

    Do not call Hooks inside:

    • conditions
    • loops
    • nested functions
    • event handlers
    • try/catch/finally blocks
    • other callbacks

    Do Not Call Hooks Inside Conditions

    Incorrect:

    javascript
    function Profile({ isLoggedIn }) {
    if (isLoggedIn) {
    const [user, setUser] = useState(null);
    }
    return <div>Profile</div>;
    }

    The Hook is conditional.

    Instead:

    javascript
    function Profile({ isLoggedIn }) {
    const [user, setUser] = useState(null);
    if (!isLoggedIn) {
    return <p>Please log in.</p>;
    }
    return <div>Profile</div>;
    }

    The Hook is always called.

    The condition controls what the component renders, not whether the Hook exists.

    Do Not Call Hooks Inside Loops

    Incorrect:

    javascript
    function Products({ products }) {
    for (const product of products) {
    const [selected, setSelected] = useState(false);
    }
    return <div>Products</div>;
    }

    The number of Hook calls could change when the number of products changes.

    Instead, move the Hook into a child component:

    javascript
    function Product({ product }) {
    const [selected, setSelected] = useState(false);
    return (
    <div>
    <button onClick={() => setSelected((value) => !value)}>
    {selected ? "Selected" : "Select"}
    </button>
    <span>{product.name}</span>
    </div>
    );
    }
    function Products({ products }) {
    return (
    <div>
    {products.map((product) => (
    <Product
    key={product.id}
    product={product}
    />
    ))}
    </div>
    );
    }

    Each Product component has its own state.

    This is a common and important React pattern.

    Do Not Call Hooks Inside Nested Functions

    Incorrect:

    javascript
    function Component() {
    function initialize() {
    const [value, setValue] = useState(0);
    }
    return <div />;
    }

    The Hook is inside a nested function.

    Instead:

    javascript
    function Component() {
    const [value, setValue] = useState(0);
    function initialize() {
    setValue(0);
    }
    return <div />;
    }

    Hooks belong at the top level.

    Do Not Call Hooks Inside Event Handlers

    Incorrect:

    javascript
    function Component() {
    function handleClick() {
    const [value, setValue] = useState(0);
    }
    return (
    <button onClick={handleClick}>
    Click
    </button>
    );
    }

    An event handler runs in response to an event. It is not a component render.

    Instead:

    javascript
    function Component() {
    const [value, setValue] = useState(0);
    function handleClick() {
    setValue((current) => current + 1);
    }
    return (
    <button onClick={handleClick}>
    {value}
    </button>
    );
    }

    Do Not Call Hooks Inside Callbacks

    Incorrect:

    javascript
    function Component() {
    const calculate = () => {
    const [value, setValue] = useState(0);
    };
    return <div />;
    }

    Hooks must not be placed inside arbitrary callbacks.

    This also applies to callbacks passed to array methods:

    javascript
    items.map(() => {
    const [value, setValue] = useState(0);
    });

    If each item needs state, create a component for the item.

    Do Not Call Hooks Inside try/catch/finally

    Avoid:

    javascript
    function Component() {
    try {
    const [value, setValue] = useState(0);
    } catch (error) {
    // ...
    }
    return <div />;
    }

    Hook calls should remain at the top level.

    Instead:

    javascript
    function Component() {
    const [value, setValue] = useState(0);
    try {
    // regular logic
    } catch (error) {
    // handle error
    }
    return <div />;
    }

    The Hook itself remains unconditional.

    The Correct Pattern

    This is good:

    javascript
    function Dashboard() {
    const [user, setUser] = useState(null);
    const [loading, setLoading] = useState(false);
    const [error, setError] = useState(null);
    if (loading) {
    return <p>Loading...</p>;
    }
    if (error) {
    return <p>Error</p>;
    }
    return <p>Dashboard</p>;
    }

    Notice:

    text
    Hooks
    ↓
    Conditional rendering
    ↓
    UI

    Not:

    text
    Conditional logic
    ↓
    Hooks

    Rule 2: Only Call Hooks from React Functions

    Hooks should be called from:

    • React function components
    • Custom Hooks

    Good:

    javascript
    function Counter() {
    const [count, setCount] = useState(0);
    return <p>{count}</p>;
    }

    Good:

    javascript
    function useCounter() {
    const [count, setCount] = useState(0);
    return [count, setCount];
    }

    Avoid calling Hooks from ordinary utility functions.

    Hooks Inside Regular Functions

    Incorrect:

    javascript
    function calculateValue() {
    const [value, setValue] = useState(0);
    return value;
    }

    If calculateValue is just a utility function, it should not call Hooks.

    Instead:

    javascript
    function calculateValue(value) {
    return value * 2;
    }

    If the function genuinely represents reusable stateful behavior, turn it into a Custom Hook:

    javascript
    function useValue() {
    const [value, setValue] = useState(0);
    return [value, setValue];
    }

    The name should communicate that it is a Hook.

    Custom Hooks Must Follow the Same Rules

    A Custom Hook can call other Hooks:

    javascript
    function useOnlineStatus() {
    const [isOnline, setIsOnline] = useState(true);
    useEffect(() => {
    // ...
    }, []);
    return isOnline;
    }

    But the Custom Hook itself must follow the Rules of Hooks.

    Incorrect:

    javascript
    function useOnlineStatus(enabled) {
    if (enabled) {
    useEffect(() => {
    // ...
    }, []);
    }
    return true;
    }

    Instead:

    javascript
    function useOnlineStatus(enabled) {
    useEffect(() => {
    if (!enabled) {
    return;
    }
    // ...
    }, [enabled]);
    return true;
    }

    The Hook is always called.

    The condition is inside the Hook's logic.

    Conditional Logic Inside Hooks

    A common misunderstanding is:

    If I cannot conditionally call a Hook, how do I make a Hook conditional?

    The answer is to keep the Hook call unconditional and put the condition inside the Hook.

    Incorrect:

    javascript
    if (enabled) {
    useEffect(() => {
    // ...
    }, []);
    }

    Correct:

    javascript
    useEffect(() => {
    if (!enabled) {
    return;
    }
    // Effect logic
    }, [enabled]);

    This preserves the Hook call order.

    Conditional Effects

    Suppose a subscription should only be active when enabled.

    Use:

    javascript
    useEffect(() => {
    if (!enabled) {
    return;
    }
    const connection = connect();
    return () => {
    connection.disconnect();
    };
    }, [enabled]);

    The Effect Hook is always called.

    The Effect decides whether there is work to perform.

    This pattern is useful for:

    • subscriptions
    • timers
    • event listeners
    • API synchronization
    • browser APIs

    Conditional State Initialization

    You may need state that depends on a condition.

    Do not conditionally call useState.

    Incorrect:

    javascript
    if (isAdmin) {
    const [settings, setSettings] = useState({});
    }

    Instead:

    javascript
    const [settings, setSettings] = useState(
    isAdmin ? defaultAdminSettings : defaultUserSettings
    );

    Or use a lazy initializer:

    javascript
    const [settings, setSettings] = useState(() =>
    createInitialSettings(isAdmin)
    );

    The Hook call itself remains unconditional.

    Hooks and Early Returns

    This is an important distinction.

    An early return after all Hook calls is fine:

    javascript
    function Profile({ user }) {
    const [loading, setLoading] = useState(false);
    if (!user) {
    return <p>No user.</p>;
    }
    return <p>{user.name}</p>;
    }

    But this is problematic:

    javascript
    function Profile({ user }) {
    if (!user) {
    return <p>No user.</p>;
    }
    const [loading, setLoading] = useState(false);
    return <p>{user.name}</p>;
    }

    On some renders, the Hook is called and on others it is not.

    The safe pattern is:

    text
    Call Hooks
    ↓
    Check conditions
    ↓
    Return UI

    Hooks and Component Loops

    A common beginner mistake is trying to create state dynamically inside a loop.

    Incorrect:

    javascript
    function Form({ fields }) {
    return fields.map((field) => {
    const [value, setValue] = useState("");
    return (
    <input
    key={field.name}
    value={value}
    onChange={(event) => setValue(event.target.value)}
    />
    );
    });
    }

    Instead, extract a component:

    javascript
    function Field({ field }) {
    const [value, setValue] = useState("");
    return (
    <input
    value={value}
    onChange={(event) => setValue(event.target.value)}
    />
    );
    }
    function Form({ fields }) {
    return (
    <>
    {fields.map((field) => (
    <Field
    key={field.name}
    field={field}
    />
    ))}
    </>
    );
    }

    Now each field is a separate component instance with its own state.

    Hooks and Dynamic Component Data

    React's component model naturally solves many dynamic-state problems.

    Instead of:

    text
    One component
    ├── Hook for item 1
    ├── Hook for item 2
    ├── Hook for item 3
    └── ...

    Use:

    text
    Parent Component
    ↓
    List of Child Components
    ├── Item 1 → own Hooks
    ├── Item 2 → own Hooks
    └── Item 3 → own Hooks

    This makes state ownership explicit.

    Hook Order

    The Rules of Hooks are fundamentally about preserving a stable order of Hook calls.

    Consider:

    javascript
    function Component() {
    const [a, setA] = useState("A");
    const [b, setB] = useState("B");
    const [c, setC] = useState("C");
    // ...
    }

    Conceptually:

    text
    Hook #1 → a
    Hook #2 → b
    Hook #3 → c

    React expects that order to remain consistent.

    Do not change it with conditional Hook calls.

    What Goes Wrong with Conditional Hooks?

    Imagine:

    javascript
    function Component({ showExtra }) {
    const [first, setFirst] = useState("first");
    if (showExtra) {
    const [second, setSecond] = useState("second");
    }
    const [third, setThird] = useState("third");
    // ...
    }

    When showExtra is true:

    text
    Hook #1 → first
    Hook #2 → second
    Hook #3 → third

    When it is false:

    text
    Hook #1 → first
    Hook #2 → third

    The positions no longer represent the same state variables.

    This is why conditional Hook calls are invalid.

    Hook Order Mental Model

    Think of Hooks as a sequence:

    text
    Render 1
    useState
    useEffect
    useRef
    useMemo

    Render 2 should have the same sequence:

    text
    Render 2
    useState
    useEffect
    useRef
    useMemo

    Not:

    text
    Render 2
    useState
    useRef
    useMemo

    The order must remain stable.

    Hooks and Nested Components

    Hooks belong to the component whose state they manage.

    Good:

    javascript
    function UserCard({ user }) {
    const [expanded, setExpanded] = useState(false);
    return (
    <article>
    <button
    onClick={() =>
    setExpanded((value) => !value)
    }
    >
    Toggle
    </button>
    {expanded && <p>{user.email}</p>}
    </article>
    );
    }

    If you have multiple user cards:

    javascript
    function UserList({ users }) {
    return (
    <>
    {users.map((user) => (
    <UserCard
    key={user.id}
    user={user}
    />
    ))}
    </>
    );
    }

    Each UserCard gets its own Hook state.

    Hooks and Component Definitions

    Avoid defining components dynamically inside another component when it causes unnecessary remounting or makes Hook ownership confusing.

    Prefer:

    javascript
    function UserCard({ user }) {
    const [expanded, setExpanded] = useState(false);
    return <div>{/* ... */}</div>;
    }
    function UserList({ users }) {
    return users.map((user) => (
    <UserCard
    key={user.id}
    user={user}
    />
    ));
    }

    This gives React a stable component type.

    The eslint-plugin-react-hooks Rule

    The React ecosystem provides ESLint support for detecting many incorrect Hook patterns.

    A typical React project can use the Hooks lint rules to catch issues such as:

    • Hooks called conditionally
    • Hooks called inside loops
    • invalid dependency arrays
    • incorrect Custom Hook usage

    The lint rules are extremely useful because many Hook mistakes are structural and can be detected before runtime.

    A modern React project should generally keep its React Hooks linting enabled.

    Rules of Hooks vs Dependency Rules

    These concepts are related but different.

    Rules of Hooks

    They answer:

    Where can Hooks be called?

    Examples:

    javascript
    useState()
    useEffect()
    useRef()

    They must be called from valid locations and at the top level.

    Effect Dependency Rules

    They answer:

    Which reactive values does an Effect, Memo, or Callback depend on?

    Example:

    javascript
    useEffect(() => {
    console.log(user.name);
    }, [user]);

    These are different concerns.

    A component can follow the Rules of Hooks while still having an incorrect dependency array.

    Both need attention.

    Example: Correct Hook Usage

    javascript
    import {
    useEffect,
    useMemo,
    useState,
    } from "react";
    function ProductList({ products, query }) {
    const [isVisible, setIsVisible] = useState(true);
    const filteredProducts = useMemo(() => {
    return products.filter((product) =>
    product.name
    .toLowerCase()
    .includes(query.toLowerCase())
    );
    }, [products, query]);
    useEffect(() => {
    document.title = `${filteredProducts.length} Products`;
    }, [filteredProducts.length]);
    if (!isVisible) {
    return null;
    }
    return (
    <ul>
    {filteredProducts.map((product) => (
    <li key={product.id}>
    {product.name}
    </li>
    ))}
    </ul>
    );
    }

    All Hooks are called before the conditional return.

    Example: Incorrect Hook Usage

    javascript
    function ProductList({ products, query, enabled }) {
    if (!enabled) {
    return null;
    }
    const [isVisible, setIsVisible] = useState(true);
    if (query) {
    useEffect(() => {
    // ...
    }, [query]);
    }
    return <div />;
    }

    Problems:

    • useState occurs after an early return.
    • useEffect is conditional.

    A safer structure:

    javascript
    function ProductList({ products, query, enabled }) {
    const [isVisible, setIsVisible] = useState(true);
    useEffect(() => {
    if (!enabled || !query) {
    return;
    }
    // Effect logic
    }, [enabled, query]);
    if (!enabled) {
    return null;
    }
    return <div />;
    }

    Hooks in Custom Hook Composition

    Custom Hooks can call other Custom Hooks at the top level.

    Good:

    javascript
    function useProductSearch(query) {
    const debouncedQuery = useDebounce(query, 500);
    const { data, loading, error } =
    useProducts(debouncedQuery);
    return {
    data,
    loading,
    error,
    };
    }

    The calls remain unconditional.

    Each Custom Hook can manage its own internal logic while following the same rules.

    Do Not Hide Conditional Hook Calls

    Renaming a function does not make invalid Hook usage valid.

    For example:

    javascript
    function createState() {
    return useState(0);
    }

    Calling:

    javascript
    createState();

    does not make the Hook safe.

    If a function uses Hooks, it should be clearly designed as a Custom Hook:

    javascript
    function useCounter() {
    return useState(0);
    }

    Then use it from a component or another Custom Hook:

    javascript
    function Counter() {
    const [count, setCount] = useCounter();
    return <p>{count}</p>;
    }

    Common Mistakes

    1. Calling Hooks in if Statements

    Incorrect:

    javascript
    if (condition) {
    useEffect(() => {});
    }

    Call the Hook unconditionally.

    2. Calling Hooks in Loops

    Incorrect:

    javascript
    items.forEach(() => {
    useState();
    });

    Move the state into a child component or use a single state structure.

    3. Calling Hooks in Event Handlers

    Incorrect:

    javascript
    function handleClick() {
    useState();
    }

    Use state at the component level.

    4. Calling Hooks in Utility Functions

    Incorrect:

    javascript
    function formatData() {
    useState();
    }

    Use a normal helper for pure calculations.

    5. Calling Hooks After an Early Return

    Incorrect:

    javascript
    if (!user) {
    return null;
    }
    const [value, setValue] = useState("");

    Move the Hook before the return.

    6. Creating Dynamic Hook Counts

    Avoid:

    javascript
    items.map(() => useState());

    The number of Hook calls should not depend on dynamic data.

    7. Confusing Conditional Logic with Conditional Hook Calls

    This is allowed:

    javascript
    useEffect(() => {
    if (!enabled) {
    return;
    }
    // logic
    }, [enabled]);

    This is not:

    javascript
    if (enabled) {
    useEffect(() => {
    // logic
    }, []);
    }

    Best Practices

    1. Keep Hooks at the Top

    A clean component often starts with:

    javascript
    function Component() {
    const state = useState();
    const ref = useRef();
    useEffect(() => {
    // ...
    }, []);
    // rendering logic
    }

    2. Separate Hook Calls from Rendering Logic

    A useful mental structure is:

    text
    Component
    ├── Hook calls
    ├── Event handlers
    ├── Derived values
    └── JSX

    3. Use Child Components for Repeated Stateful Items

    If each item needs independent state, create a component for the item.

    4. Keep Custom Hooks Clearly Named

    Use:

    javascript
    useSearch()
    useAuth()
    useForm()

    This makes Hook usage obvious.

    5. Keep Hook Dependencies Accurate

    Rules of Hooks do not eliminate the need to maintain correct dependency arrays.

    6. Enable Hook Linting

    Use React's ESLint Hook rules to catch structural problems early.

    7. Avoid Clever Hook Abstractions

    Do not hide Hook calls inside confusing utility layers.

    Prefer straightforward, readable Hook composition.

    Debugging Hook Rule Errors

    When you see a Hook-related error, ask:

    Question 1

    Is the Hook called from a React component or Custom Hook?

    Question 2

    Is the Hook inside:

    text
    if
    loop
    nested function
    event handler
    callback
    try/catch

    ?

    Question 3

    Can an early return happen before the Hook?

    Question 4

    Can the number of Hook calls change between renders?

    Question 5

    Is the function actually a Custom Hook?

    This checklist resolves many Hook-order problems.

    Practical Example: Fixing a Conditional Hook

    Incorrect:

    javascript
    function Chat({ connected }) {
    if (!connected) {
    return <p>Disconnected</p>;
    }
    useEffect(() => {
    console.log("Connected");
    }, []);
    return <p>Connected</p>;
    }

    The Effect is not called when disconnected.

    Correct:

    javascript
    function Chat({ connected }) {
    useEffect(() => {
    if (!connected) {
    return;
    }
    console.log("Connected");
    }, [connected]);
    if (!connected) {
    return <p>Disconnected</p>;
    }
    return <p>Connected</p>;
    }

    Now the Hook is called on every render.

    The Effect decides whether it has work to perform.

    Practical Example: Per-Item State

    Incorrect:

    javascript
    function TodoList({ todos }) {
    return todos.map((todo) => {
    const [editing, setEditing] = useState(false);
    return (
    <div key={todo.id}>
    {todo.text}
    </div>
    );
    });
    }

    Correct:

    javascript
    function TodoItem({ todo }) {
    const [editing, setEditing] = useState(false);
    return (
    <div>
    <button
    onClick={() =>
    setEditing((value) => !value)
    }
    >
    Edit
    </button>
    {editing ? (
    <input defaultValue={todo.text} />
    ) : (
    <span>{todo.text}</span>
    )}
    </div>
    );
    }
    function TodoList({ todos }) {
    return (
    <div>
    {todos.map((todo) => (
    <TodoItem
    key={todo.id}
    todo={todo}
    />
    ))}
    </div>
    );
    }

    Each TodoItem owns its own editing state.

    Practice Exercises

    Exercise 1: Fix Conditional Hooks

    Given:

    javascript
    function Component({ enabled }) {
    if (enabled) {
    const [value, setValue] = useState(0);
    }
    return <div />;
    }

    Rewrite it so it follows the Rules of Hooks.

    Exercise 2: Fix a Conditional Effect

    Given:

    javascript
    function Chat({ connected }) {
    if (connected) {
    useEffect(() => {
    connect();
    }, []);
    }
    return <div />;
    }

    Rewrite the component correctly.

    Exercise 3: Fix Hook Usage in a Loop

    Given:

    javascript
    function List({ items }) {
    return items.map((item) => {
    const [selected, setSelected] = useState(false);
    return <div>{item.name}</div>;
    });
    }

    Extract an appropriate child component.

    Exercise 4: Identify the Invalid Hook

    Which Hook usage is invalid?

    javascript
    function Example() {
    const [count, setCount] = useState(0);
    useEffect(() => {
    console.log(count);
    }, [count]);
    return <p>{count}</p>;
    }
    javascript
    function Example() {
    const [count, setCount] = useState(0);
    if (count > 0) {
    useEffect(() => {
    console.log(count);
    }, [count]);
    }
    return <p>{count}</p>;
    }

    Explain why.

    Exercise 5: Custom Hook Rules

    Create:

    javascript
    useOnlineStatus()

    Make sure:

    • Hooks are called at the top level.
    • Event listeners are registered in an Effect.
    • cleanup is returned from the Effect.
    • the Hook can be called from multiple components.

    Exercise 6: Refactor a Dynamic Form

    Create a form where each field is rendered through a child component.

    Each field should manage its own temporary UI state without calling Hooks inside the parent's .map() callback.

    Mini Project: Hook Rules Refactoring

    Start with a deliberately problematic component:

    javascript
    function Dashboard({ user, items, enabled }) {
    if (!enabled) {
    return null;
    }
    if (user) {
    const [expanded, setExpanded] =
    useState(false);
    }
    return items.map((item) => {
    const [selected, setSelected] =
    useState(false);
    return (
    <div key={item.id}>
    {item.name}
    </div>
    );
    });
    }

    Refactor it.

    Requirements:

    • no conditional Hook calls
    • no Hook calls inside .map()
    • use child components for item-level state
    • keep Hooks at the top level
    • preserve the UI behavior
    • use clear component boundaries

    Possible architecture:

    text
    Dashboard
    ↓
    Dashboard-level Hooks
    ↓
    ItemList
    ↓
    Item
    ↓
    Item-level Hooks

    This exercise demonstrates why the Rules of Hooks influence component architecture.

    Interview questions & answers

    Interview preparation

    8 questions grouped by difficulty — expand any card for a model answer and follow-up probe.

    Beginner

    3
    1. 1What are the Rules of Hooks?
      Beginner

      Model answer

      The fundamental rules are:
      1. Only call Hooks at the top level.
      2. Only call Hooks from React function components or Custom Hooks.
    2. 2Can Hooks be called inside event handlers?
      Beginner

      Model answer

      No.

      Event handlers run after rendering.

      Hooks must be called during the component or Custom Hook's execution at the top level.

    3. 3Can you return early from a component before calling Hooks?
      Beginner

      Model answer

      If that return can happen on some renders and Hooks would be called afterward on other renders, no. Call the Hooks first: const [state, setState] = useState(); → if (!data) { → return null; → }

    Intermediate

    3
    1. 4Why can't Hooks be called conditionally?
      Intermediate

      Model answer

      React relies on a stable order of Hook calls between renders.

      Conditional calls can change that order and cause state to be associated with the wrong Hook.

    2. 5Can a Custom Hook call another Custom Hook?
      Intermediate

      Model answer

      Yes. function useSearch(query) { → const debouncedQuery = useDebounce(query, 500); → // ... → } This is normal Hook composition.
    3. 6Why are Custom Hook names prefixed with use?
      Intermediate

      Model answer

      The convention identifies functions that use Hooks and allows React tooling and developers to recognize that they must follow the Rules of Hooks.

    Advanced

    2
    1. 7Can Hooks be used inside loops?
      Advanced

      Model answer

      No.

      If repeated items need independent Hook state, extract the repeated item into a component.

    2. 8Can you conditionally run an Effect?
      Advanced

      Model answer

      Yes, but not by conditionally calling useEffect. Correct: useEffect(() => { → if (!enabled) { → return; → } → // effect logic → }, [enabled]);

    Rules of Hooks Cheat Sheet

    Rule 1

    Call Hooks at the top level.

    Good:

    javascript
    function Component() {
    const [count, setCount] = useState(0);
    if (count > 10) {
    return <p>High</p>;
    }
    return <p>{count}</p>;
    }

    Bad:

    javascript
    function Component() {
    if (condition) {
    const [count, setCount] = useState(0);
    }
    }

    Rule 2

    Call Hooks only from React functions.

    Good:

    javascript
    function Component() {
    useState();
    }

    Good:

    javascript
    function useSomething() {
    useState();
    }

    Bad:

    javascript
    function helper() {
    useState();
    }

    Conditional Effect

    Good:

    javascript
    useEffect(() => {
    if (!enabled) {
    return;
    }
    // work
    }, [enabled]);

    Bad:

    javascript
    if (enabled) {
    useEffect(() => {
    // work
    }, []);
    }

    Repeated item state

    Good:

    javascript
    function Item() {
    const [selected, setSelected] = useState(false);
    return <div />;
    }

    Bad:

    javascript
    items.map(() => {
    const [selected, setSelected] = useState(false);
    });

    Key Takeaways

    Ready to mark this lesson complete?Track your journey across the entire course.