You've been using a hook since lesson 02-04 without putting a name to the category: useState. And the last two lessons have surfaced the historical reasons hooks exist: the wrapper hell of HOCs and render props (04-02), and related logic scattered across lifecycle methods that sat fifty lines apart from each other (04-03). This lesson closes that loop. You'll understand exactly what a hook is, what problem it came to solve, why it has two apparently arbitrary rules of use — and the internal mechanism that explains them —, what hooks exist and which lesson in the course covers each one. We won't develop any of them in depth here: that's the job of the entire Module 5. Here we're laying out the map before we walk the territory.
Contents
- What problem hooks came to solve
- What a hook is, precisely
- Rule 1: only at the top level
- The mechanism: the ordered list of hooks
- Rule 2: only from components or from other hooks
eslint-plugin-react-hooks, the safety net- Catalogue of the course's hooks
- Combined basic use:
SummaryPanelwithuseState+useEffect - Local state, ref, and context: three different things
- What problem hooks came to solve
Before 2019, a React component had to pick between two incompatible shapes:
- Function component: simple, readable, no
this… but no state and no access to the lifecycle. Good only for presentation. - Class component: could do everything, at the cost of a constructor,
bind,this, and lifecycle methods.
That forced a full refactor the moment a presentational component needed to remember a piece of data. But the deeper problem was something else, and worse: there was no decent way to reuse stateful logic.
Say three CicloUrbano components need to know the window's width to decide how many cards fit. With classes, the logic — subscribe to the resize event, store the width, unsubscribe — had to be copied into all three, or the three had to be wrapped in a HOC, or nested inside a render prop. The last two options produced trees like this one:
// What used to show up in React DevTools with four stacked HOCs
<withAuth(withTheme(withWidth(withLogging(OperatorPanel))))>
<withTheme(withWidth(withLogging(OperatorPanel)))>
<withWidth(withLogging(OperatorPanel))>
<withLogging(OperatorPanel)>
<OperatorPanel /> ← the only one that paints anythingFour levels that paint nothing, props that appear with no visible origin, and awkward debugging. That's the wrapper hell you saw in 04-02.
The second problem was organization by moment instead of by subject, which we analysed in 04-03:
componentDidMount() {
this.loadBikes(); // concern A
window.addEventListener('resize', this.measureWidth); // concern B
this.timer = setInterval(this.updateClock, 1000); // concern C
}
componentWillUnmount() {
window.removeEventListener('resize', this.measureWidth); // concern B, down here
clearInterval(this.timer); // concern C, down here
}Three concerns that have nothing to do with each other share a method, and each one has its other half in a different method. It's the perfect recipe for forgetting a cleanup.
Hooks solve all three at once:
| Previous problem | What hooks answer with |
|---|---|
| Functions couldn't have state | useState and friends work in any function component |
| Reusing stateful logic required wrappers | A custom hook is a function call, with no extra level in the tree |
| Related logic ended up scattered | Each concern gets its own block, with its cleanup right next to it |
this and bind |
Gone: there's no class |
And one thing they didn't do: get rid of classes. They still work, and error boundaries still require them (04-05).
- What a hook is, precisely
A hook is a JavaScript function whose name starts with
useand that hooks the component into React's internal system, giving it access to capabilities like state, effects, or context.
Let's unpack the definition:
- It's an ordinary function. It isn't a language keyword, it isn't special syntax, it doesn't require compilation.
useStateis a function React exports and you import. - Its name starts with
use. That's not decorative: it's the convention by which React and analysis tools recognize a hook.eslint-plugin-react-hooksdecides whether a function is a hook by looking at its name, and applies the rules accordingly. If you write your own stateful function and call itgetWidthinstead ofuseWidth, the rules won't apply and you'll lose the safety net. - It hooks into the internal system. Here's the conceptual key. A function component is just a function: when it finishes, its variables disappear. So where does state get stored between renders? Outside the component, in an internal data structure of React's, tied to that specific instance. The hook is the cable that connects the function to that store.
function DockCounter() {
const [docks, setDocks] = useState(20);
// `docks` is a local variable that dies when the function finishes.
// The VALUE 20 (and then 19, 18…) doesn't live here: it lives inside React.
// useState is the cable that goes and fetches it on every render.
return <p>Free docks: {docks}</p>;
}That idea — state lives in React, not in the function — is what makes the two rules in the next section possible. It also explains something you already noticed in 02-04: two instances of the same component have independent states, because React keeps one store per instance, not per component.
- Rule 1: only at the top level
Call hooks only at the top level of the component. Never inside conditionals, loops, nested functions, or after an early
return.
// CORRECT: all three hooks, at the top level, always in the same order
function AdvancedBookingPanel({ bike }) {
const [hours, setHours] = useState(1);
const [confirmed, setConfirmed] = useState(false);
const reference = useRef(null);
if (!bike) {
return <p>Select a bike.</p>; // the return comes AFTER the hooks
}
// …
}// INCORRECT: the hook is inside an if
function AdvancedBookingPanel({ bike }) {
if (bike) {
const [hours, setHours] = useState(1); // ❌
}
// …
}// INCORRECT: early return BEFORE a hook
function AdvancedBookingPanel({ bike }) {
const [hours, setHours] = useState(1);
if (!bike) return null; // ❌ the next hook sometimes doesn't run
const [confirmed, setConfirmed] = useState(false);
// …
}// INCORRECT: hook inside a loop
function CounterList({ stations }) {
return stations.map((station) => {
const [docks, setDocks] = useState(station.docks); // ❌
return <p key={station.id}>{docks}</p>;
});
}The last case has a conceptual fix, not a technical one: if each station needs its own state, each station needs its own component. You extract DockCounter and call the hook inside it. Each instance gets its own store, and the rule holds on its own.
Why such strict rules? Because React's internal mechanism depends on order. Let's see it.
- The mechanism: the ordered list of hooks
React doesn't store state by the variable's name. It can't: const [hours, setHours] is array destructuring, and React never sees the name hours. What it does is much simpler: for every component instance, it keeps an ordered list of cells, and a pointer that moves forward one position with every hook call.
flowchart LR
subgraph R1["First render"]
H1["useState(1)"] --> C1["cell 0<br/>value: 1"]
H2["useState(false)"] --> C2["cell 1<br/>value: false"]
H3["useRef(null)"] --> C3["cell 2<br/>value: {current: null}"]
end
subgraph R2["Subsequent renders"]
S1["useState(1)"] --> D1["reads cell 0"]
S2["useState(false)"] --> D2["reads cell 1"]
S3["useRef(null)"] --> D3["reads cell 2"]
end
R1 --> R2
On the first render React creates the cells in the order the hooks are called. On every subsequent render it simply reads them in the same order. The link between useState(1) and its stored value is exclusively position.
That's where the rule comes from: if a render calls three hooks and the next one calls only two, the positions shift and every variable ends up with someone else's value.
The disaster, step by step
// BROKEN CODE, to understand the mechanism
function BookingPanel({ bike }) {
const [hours, setHours] = useState(1); // cell 0
if (bike) {
const [note, setNote] = useState(''); // ❌ cell 1 only sometimes
}
const [confirmed, setConfirmed] = useState(false); // cell 1 or cell 2?
// …
}sequenceDiagram
participant R1 as Render 1 (bike = object)
participant M as React's cells
participant R2 as Render 2 (bike = null)
R1->>M: useState(1) → cell 0 = 1
R1->>M: useState('') → cell 1 = ''
R1->>M: useState(false) → cell 2 = false
Note over M: [1, '', false]
R2->>M: useState(1) → reads cell 0 = 1 ✅
R2->>M: (the if doesn't hold: no call happens)
R2->>M: useState(false) → reads cell 1 = '' ❌
Note over R2: `confirmed` ends up as ''<br/>(a string) instead of false
The result on screen: confirmed ends up holding '' instead of false, and setConfirmed writes into the cell that used to belong to note. There's no syntax error, the app doesn't crash, and the bug shows up as absurd behaviour that's very hard to trace. React catches many of these cases and warns with:
Warning: React has detected a change in the order of Hooks called by BookingPanel.
This will lead to bugs and errors if not fixed.When you see that message, look for a hook inside an if, a loop, a try/catch, or after an early return. It's always that.
The practical consequence: the number and order of hook calls must be identical on every render of a component. That's why hooks are all written together, right at the top, before any conditional logic. And if you need a conditional value, the condition goes inside the hook, not around it:
// Instead of putting the hook inside the if, put the if inside the hook
const [note, setNote] = useState(bike ? '' : 'no bike');
- Rule 2: only from components or from other hooks
Call hooks only from React function components or from other custom hooks. Never from plain JavaScript functions.
// CORRECT: from a component
function FleetSummary({ fleet }) {
const [order, setOrder] = useState('model');
// …
}
// CORRECT: from a custom hook (name starts with use)
function useSortedFleet(fleet) {
const [order, setOrder] = useState('model');
return { order, setOrder };
}
// INCORRECT: from a plain function
function calculateAvailable(fleet) {
const [counter, setCounter] = useState(0); // ❌ which component does this state belong to?
return fleet.filter((b) => b.status === 'disponible').length;
}
// INCORRECT: from an event handler
function handleClick() {
const [open, setOpen] = useState(false); // ❌ runs outside of render
}The reason follows straight from the previous section: the cells belong to a component instance that's rendering right now. If you call a hook from a loose function, React has no idea which cell list to reach for, and it throws:
The event handler case deserves a warning, because it's a frequent mistake for beginners: handlers run after render, once no rendering is in progress anymore. Hooks get called during render; handlers use whatever those hooks returned.
// The correct pattern
function BikeCard({ bike }) {
const [featured, setFeatured] = useState(false); // hook: during render
function handleClick() {
setFeatured(!featured); // handler: uses the result
}
return <article onClick={handleClick}>…</article>;
}And the constructive consequence of this rule is the one that gives everything meaning: a function whose name starts with use and calls hooks is a custom hook, and that's all it takes to reuse stateful logic. No wrappers, no new levels in the tree. You'll build one in Custom Hooks.
eslint-plugin-react-hooks, the safety net
eslint-plugin-react-hooks, the safety netThe two rules are easy to break without noticing, especially while refactoring. That's why the React team maintains an ESLint plugin that checks them automatically, and that Vite's React templates already ship configured.
// eslint.config.js (excerpt)
import reactHooks from 'eslint-plugin-react-hooks';
export default [
{
plugins: { 'react-hooks': reactHooks },
rules: {
'react-hooks/rules-of-hooks': 'error', // the two rules from this lesson
'react-hooks/exhaustive-deps': 'warn' // effect dependencies (05-02)
}
}
];What each rule contributes:
| Rule | What it catches | Recommended severity |
|---|---|---|
rules-of-hooks |
Hooks in conditionals, loops, plain functions, or handlers | error: there are no false positives that would justify ignoring it |
exhaustive-deps |
Missing or extra dependencies in useEffect, useMemo, and useCallback |
warn: it's almost always right, but there are legitimate exceptions |
The first rule is wrong so rarely that it's worth treating as a compile error. If you're ever tempted to silence it with a comment, the correct answer is almost always to restructure the component — extract a child component, move the condition inside the hook — not to silence the warning.
- Catalogue of the course's hooks
Here's the full map. Don't memorize the details now: the right-hand column tells you where each one gets explained in depth.
| Hook | What it's for, in one sentence | Where it's studied |
|---|---|---|
useState |
Store a value that changes and triggers a new render when it changes | 05-01 |
useEffect |
Synchronize the component with an external system (timers, network, subscriptions) | 05-02 |
useRef |
Store a value without triggering renders, and access DOM nodes | 05-03 |
useContext |
Read a value shared by an entire subtree, without prop drilling | 05-04 |
useReducer |
Manage complex state with many transitions, via actions and a reducer | 05-05 |
useMemo |
Remember the result of an expensive calculation across renders | 08-03 |
useCallback |
Remember a function across renders so it doesn't break the children's memoization | 08-03 |
useId |
Generate a unique, stable identifier to associate a label with fields |
05-03 (mention) and accessibility from 03-06 |
useTransition |
Mark an update as non-urgent so it doesn't block the interface | Module 8 |
useDeferredValue |
Show a "lagging" version of a value while the final one arrives | Module 8 |
use |
Read a promise or a context directly during render (React 19) | Module 10 |
| Custom hooks | Package your own stateful logic into a reusable function | 05-06 |
Two observations about the catalogue:
- Most components only need
useState. After that, by frequency, comeuseEffectanduseContext.useMemoanduseCallbackare optimization tools that only apply once you've measured a problem, and that's exactly why they show up in module 8. - There are more hooks than the ones listed here (
useImperativeHandle,useSyncExternalStore,useDebugValue,useOptimistic,useActionState…). They're specialized, and this course leaves them out except for the odd mention. The table above covers ninety-five percent of the React written on a daily basis.
- Combined basic use:
SummaryPanel with useState + useEffect
SummaryPanel with useState + useEffectA taste of module 5. This CicloUrbano component combines the two hooks you'll use most: it keeps a count of how many times the summary has been queried, and it synchronizes the browser tab's title with the available fleet.
// src/components/SummaryPanel.jsx
import { useState, useEffect } from 'react';
import styles from './SummaryPanel.module.css';
/**
* Queryable summary of CicloUrbano's fleet.
* Props:
* - fleet (array of Bike, required)
*/
function SummaryPanel({ fleet }) {
const [queries, setQueries] = useState(0);
const [message, setMessage] = useState('Click to refresh the summary.');
// DERIVED values: recomputed on every render, they aren't state (04-01)
const available = fleet.filter((bike) => bike.status === 'disponible').length;
const inMaintenance = fleet.filter((bike) => bike.status === 'mantenimiento').length;
// EFFECT: synchronizes the document title with the number available
useEffect(() => {
document.title = `CicloUrbano · ${available} bikes available`;
}, [available]);
function handleQuery() {
setQueries((previousQueries) => previousQueries + 1);
setMessage(
available === 0
? 'There are no bikes available right now.'
: `${available} of ${fleet.length} bikes are ready to rent.`
);
}
return (
<section className={styles.panel}>
<h2>Fleet summary</h2>
<p>Total: {fleet.length} · Available: {available} · In maintenance: {inMaintenance}</p>
<p aria-live="polite">{message}</p>
<p className={styles.counter}>Queries made: {queries}</p>
<button type="button" onClick={handleQuery}>
Refresh summary
</button>
</section>
);
}
export default SummaryPanel;What each piece does and why it's where it is:
- The two
useStatecalls sit at the top, at the top level, one after the other. They occupy cells 0 and 1, in that order, on every render. Rule 1 satisfied. availableandinMaintenancearen't state. They're computed fromfleeton every render. If they were state, you'd have to recompute them by hand every time the fleet changed, with the desync risk you saw in 04-01.setQueries((previousQueries) => …)uses the functional form because the new value depends on the previous one. It's the precaution from 02-04.- The
useEffectsynchronizes with an external system:document.titlebelongs to the browser, not to React. This is where the mental model from 04-03 applies: it's not about "running code on mount," it's about keeping the title synchronized withavailable. That's whyavailableshows up in the dependency list[available]: whenever that number changes, the synchronization gets redone. handleQuerydoesn't call any hook. It uses the hooks' results (setQueries,setMessage,available), which is exactly the correct division of labour under rule 2.- The
aria-live="polite"comes from 03-06: the message changes without the person's focus moving, and it needs to be announced.
And in App, with no ceremony at all:
No HOC, no render props, no extra level in the tree. Two function calls inside the component, and it already has state and effects. That's the contribution of hooks, summed up in one example.
- Local state, ref, and context: three different things
To close out the map, the distinction that will organize most of the decisions you'll make in module 5:
| Tool | Stores a value that… | Triggers a render when it changes | Scope | Covered in |
|---|---|---|---|---|
State (useState) |
Shows up on screen and changes over time | Yes | The component instance | 05-01 |
Ref (useRef) |
Needs remembering but isn't painted (a timer's identifier, a DOM node) | No | The component instance | 05-03 |
Context (useContext) |
Many components far apart from each other need it (user, theme, language) | Yes, in whoever consumes it | The whole subtree under the provider | 05-04 |
In one sentence each:
- State: "what's on screen, and when it changes it needs repainting."
- Ref: "what gets remembered between renders without anyone having to repaint." It's exactly the
this.timerfromActivityPanel's class in 04-03. - Context: "what's available to a whole subtree without passing it hand to hand," the answer to the prop drilling left open in 04-01.
Common Mistakes and Tips
- A hook inside an
if, a loop, or atry. It breaks the correspondence by position and causes incomprehensible bugs. If you need conditionality, move the condition inside the hook or extract a child component. - A hook after an early
return. It's the same mistake in disguise: thereturnmakes the following lines not run on some renders. All hooks go before anyreturn. - Calling a hook from an event handler. Handlers run outside of render. Call the hook above and use its result inside the handler.
- Naming a function that calls hooks
getSomething. Without theuseprefix, the ESLint plugin doesn't recognize it as a hook and checks nothing inside it. The convention is functional, not cosmetic. - Believing that
useStatein a loop gives "one state per item." It doesn't: it gives a disaster. One state per item means one component per item. - Silencing
rules-of-hookswith an ESLint comment. That's treating the symptom. The rule is practically never wrong. - Tip: write all the hooks together, at the start of the component. State, refs, context, and effects, in that order, then the derived logic, the handlers, and the
return. Keep that layout across the whole project and following the rules becomes automatic. - Tip: look at hooks in React DevTools. Selecting a function component shows you the list of its hooks in order, with their values. It's the cell list from section 4, made visible.
Exercises
Exercise 1. This CicloUrbano component breaks the rules of hooks in three different places. Identify each violation, explain which rule it breaks and what concrete consequence it has, and rewrite the component correctly.
function StationPanel({ station, showDetail }) {
const [freeDocks, setFreeDocks] = useState(station.docks);
if (!station) {
return <p>Station not found.</p>;
}
if (showDetail) {
const [detailOpen, setDetailOpen] = useState(true);
}
function handleRental() {
const [lastRental, setLastRental] = useState(null);
setFreeDocks(freeDocks + 1);
}
return (
<article>
<h3>{station.name}</h3>
<p>Free docks: {freeDocks}</p>
<button type="button" onClick={handleRental}>Return bike</button>
</article>
);
}Exercise 2. Without writing code, say which hook you'd use for each CicloUrbano situation and which lesson covers it. Justify each choice briefly.
- Remember which bike type is filtered in the catalogue.
- Store a
setTimeout's identifier so it can be cancelled. - Have fifteen components scattered across the tree know the signed-in user.
- Keep
document.titleup to date with the number of active bookings. - Manage a booking form with eight fields and complex transitions between validation states.
Exercise 3. Extend section 8's SummaryPanel with a third piece of state, lastQuery, that stores the time of the last query as a readable string (toLocaleTimeString('en-GB')), or null if it hasn't been queried yet. Show it on screen only when it exists. Then answer: which position in the cell list does this new state land on, and why does it matter where you declare it?
Solutions
Solution 1. The three violations:
- Early
returnbefore a hook (rule 1). Whenstationis null, the function ends before reaching the following calls, and the number of hooks executed changes between renders. What's more,useState(station.docks)on the line above would already have blown up trying to read.docksoffnull: the guard arrives too late. useStateinside anif(rule 1).detailOpenonly gets created whenshowDetailis true; when that prop changes, the cells shift and the states get mixed up with each other.useStateinside an event handler (rule 2).handleRentalruns after render, when there's no render in progress: React throws "Invalid hook call."
And a fourth problem, not about the rules but about correctness: setFreeDocks(freeDocks + 1) should use the functional form, and it also has no upper bound (it could exceed the station's total docks).
function StationPanel({ station, showDetail }) {
// 1. ALL hooks at the top, unconditional and before any return
const [freeDocks, setFreeDocks] = useState(station ? station.docks : 0);
const [detailOpen, setDetailOpen] = useState(true);
const [lastRental, setLastRental] = useState(null);
// 2. Early returns, AFTER the hooks
if (!station) {
return <p>Station not found.</p>;
}
// 3. The handler uses the hooks' results; it doesn't call any
function handleRental() {
setFreeDocks((previous) => Math.min(station.docks, previous + 1));
setLastRental(new Date().toLocaleTimeString('en-GB'));
}
return (
<article>
<h3>{station.name}</h3>
<p>Free docks: {freeDocks}</p>
{showDetail && detailOpen && <p>District: {station.district}</p>}
{lastRental && <p>Last return: {lastRental}</p>}
<button type="button" onClick={handleRental}>Return bike</button>
</article>
);
}Notice the general pattern behind the fix: hooks are always all declared; what's conditional is the use of their value in the JSX, not the call itself.
Solution 2.
| Case | Hook | Lesson | Why |
|---|---|---|---|
| 1. Filtered type in the catalogue | useState |
05-01 | It's a visible value that changes with interaction and must trigger a new render. It's lived in App since 04-01 |
2. A setTimeout identifier |
useRef |
05-03 | It needs to be remembered across renders but isn't painted; changing it shouldn't repaint anything. It's the this.timer from 04-03 |
| 3. Session user, in fifteen components | useContext |
05-04 | Lifting it to App and passing it through props would cause the prop drilling flagged in 04-01 |
4. document.title up to date |
useEffect |
05-02 | The document title is a system external to React; it needs to be synchronized with a value from the component |
| 5. Eight-field form with transitions | useReducer |
05-05 | With many fields and transition rules, a reducer centralizes the logic better than eight loose useState calls |
Solution 3.
function SummaryPanel({ fleet }) {
const [queries, setQueries] = useState(0); // cell 0
const [message, setMessage] = useState('Click to refresh the summary.'); // cell 1
const [lastQuery, setLastQuery] = useState(null); // cell 2
const available = fleet.filter((bike) => bike.status === 'disponible').length;
const inMaintenance = fleet.filter((bike) => bike.status === 'mantenimiento').length;
useEffect(() => {
document.title = `CicloUrbano · ${available} bikes available`;
}, [available]);
function handleQuery() {
setQueries((previousQueries) => previousQueries + 1);
setLastQuery(new Date().toLocaleTimeString('en-GB'));
setMessage(
available === 0
? 'There are no bikes available right now.'
: `${available} of ${fleet.length} bikes are ready to rent.`
);
}
return (
<section className={styles.panel}>
<h2>Fleet summary</h2>
<p>Total: {fleet.length} · Available: {available} · In maintenance: {inMaintenance}</p>
<p aria-live="polite">{message}</p>
<p className={styles.counter}>Queries made: {queries}</p>
{lastQuery && <p>Last query: {lastQuery}</p>}
<button type="button" onClick={handleQuery}>Refresh summary</button>
</section>
);
}lastQuery occupies cell 2, because it's the third hook called. What matters isn't the number itself, but that that position stays the same across every render: that's why the declaration sits at the top level, next to the other two, and not inside the if that decides whether to show it. The condition applies only to the JSX ({lastQuery && …}), never to the hook call. If you had declared it inside a conditional, on the renders where that condition didn't hold, useEffect would end up reading the wrong cell.
Conclusion
A hook is a function whose name starts with use and that hooks a function component into React's internal system, giving it access to state, effects, context, and everything that used to require a class. Hooks were born to solve three concrete problems classes carried with them: the impossibility of giving state to a function, the wrapper hell produced by HOCs and render props (04-02), and the logic of a single concern scattered across lifecycle methods (04-03).
Their two rules — only at the top level and only from components or from other hooks — aren't stylistic whims: they're explained by the mechanism of the ordered cell list React keeps per instance. The link between a useState call and its stored value is position, and that's why the number and order of the calls must be identical on every render. eslint-plugin-react-hooks watches both rules for you, and it's worth treating rules-of-hooks as an error. You also now have the full map: which hooks exist, what each one is for, and which lesson covers it; plus a first SummaryPanel from CicloUrbano that combines useState with useEffect without a single wrapper.
One piece remains to close out the module, and it's the exception that proves everything above. Hooks have replaced lifecycle methods in everything… except one case: catching errors a component throws during render. If a CicloUrbano card blows up on unexpected data, React unmounts the whole tree and the person is left staring at a blank page. Avoiding that requires a tool that, to this day, still requires a class component. The next lesson is Error Boundaries: Catching Failures in the UI.
React Course
Module 1: Getting Started with React
- What Is React?
- Setting Up the Development Environment
- Hello World in React
- JSX: A JavaScript Syntax Extension
- How React Renders: Virtual DOM and Reconciliation
Module 2: React Components
- Understanding Components
- Function vs Class Components
- Props: Passing Data to Components
- State: Managing Component State
- Styling Components: CSS, Modules and Utilities
Module 3: Working with Events
- Handling Events in React
- Conditional Rendering
- Lists and Keys
- Forms and Controlled Components
- Form Validation and Uncontrolled Components
- Accessibility in Interactive Components
Module 4: Advanced Component Concepts
- Lifting State Up
- Composition vs Inheritance
- React Lifecycle Methods
- Hooks: Introduction and Basic Use
- Error Boundaries: Catching Failures in the UI
Module 5: React Hooks
- The useState Hook
- The useEffect Hook
- The useRef Hook and DOM Access
- The useContext Hook
- The useReducer Hook
- Custom Hooks
Module 6: Routing in React
- Introducing React Router
- Setting Up React Router
- Nested Routes
- Programmatic Navigation
- Protected Routes and Access Control
Module 7: State Management
- Introduction to State Management
- The Context API
- Redux: Introduction and Setup
- Redux: Actions and Reducers
- Redux: Connecting to React
- Server State: Fetching, Caching and Syncing
Module 8: Performance Optimization
- Performance Optimization Techniques in React
- Memoization with React.memo
- The useMemo and useCallback Hooks
- Code Splitting and Lazy Loading
- Measuring Performance with React DevTools Profiler
Module 9: Testing React Applications
- Introduction to Testing
- Unit Testing with Jest
- Component Testing with React Testing Library
- Testing Asynchronous Code and Mocking APIs
- End-to-End Testing with Cypress
Module 10: Advanced Topics
- Server-Side Rendering (SSR) with Next.js
- Static Site Generation (SSG) with Next.js
- Suspense and React Server Components
- TypeScript with React
- React Native: Building Mobile Apps
