React Hooks were introduced in React version 16.8 as a monumental shift in how developers write React applications. They allow you to use state and other React features without writing a class component.
Before Hooks, functional components were strictly "stateless." If you needed to manage state or use lifecycle methods (like componentDidMount), you were forced to convert your functional component into a Class component. Hooks completely changed this paradigm.
The introduction of Hooks solved several long-standing problems in React development:
componentDidMount).this works in JavaScript, bind event handlers, and remember the differences between class and functional components.Hooks solve these issues by letting you split one component into smaller, independent functions based on what pieces are related (such as setting up a subscription or fetching data).
A Hook is a special JavaScript function that lets you "hook into" React features. For example, useState is a Hook that lets you add React state to functional components.
Here is a quick look at a simple functional component utilizing a Hook:
import React, { useState } from 'react';function Counter() { // Declare a new state variable, which we'll call "count" const [count, setCount] = useState(0);
return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); }
In this example, useState is a Hook. We call it inside our functional component to add local state to it. React will preserve this state between re-renders.
Hooks are JavaScript functions, but they impose two additional rules that must be strictly followed to ensure they work correctly.
Do not call Hooks inside loops, conditions, or nested functions. Always use Hooks at the top level of your React function, before any early returns. This ensures that Hooks are called in the exact same order each time a component renders.
Incorrect:
function UserProfile({ name }) { if (name !== '') { // BAD: Hook inside a condition! const [age, setAge] = useState(25); } // ... }
Correct:
function UserProfile({ name }) { // GOOD: Hook at the top level! const [age, setAge] = useState(25);if (name !== '') { // Logic goes here } // ... }
Don't call Hooks from regular JavaScript functions. Instead, you can:
By following this rule, you ensure that all stateful logic in a component is clearly visible from its source code.
One of the best things about Hooks is that they are 100% backwards-compatible. They do not contain any breaking changes.
You don't have to rewrite your existing Class components. Classes are still fully supported by React and will be for the foreseeable future. However, for new components, it is highly recommended to use functional components alongside Hooks, as this is the standard for modern React development.
React provides several built-in Hooks. Throughout this tutorial section, we will cover the most important ones:
useState: To manage basic state.useEffect: To manage side effects (like data fetching and DOM manipulation).useContext: To access Context API data easily.useRef: To access DOM elements or persist mutable values without triggering re-renders.useReducer: An alternative to useState for complex state logic.useCallback & useMemo: To optimize performance by memoizing functions and values.We will dive deep into each of these hooks in the upcoming lessons!
Pro Tip: To enforce the Rules of Hooks in your codebase automatically, you can use the ESLint plugin provided by the React team: eslint-plugin-react-hooks. It is included by default if you use Create React App or Vite.
Which of the following is a strict Rule of Hooks?