⚛️ React Q12 / 113

What are React hooks?

AI-Powered Answer ✓ Answered

React Hooks are functions that let you 'hook into' React state and lifecycle features from function components. They were introduced in React 16.8, providing a way to use state and other React features without writing a class.

What are React Hooks?

Before hooks, if you needed state or lifecycle methods (like componentDidMount, componentDidUpdate, componentWillUnmount) in a React component, you had to write a class component. Function components were traditionally 'stateless' or 'presentational'. Hooks bridge this gap, allowing function components to manage state and side effects, making them as powerful as class components.

They are simple JavaScript functions that encapsulate reusable stateful logic and can be composed together. React provides several built-in hooks, and you can also create your own custom hooks.

Why were Hooks introduced?

  • Reusability of Stateful Logic: Hooks allow you to extract stateful logic from a component so it can be tested independently and reused. Custom hooks make it easy to share logic between components without props or render props.
  • Simplify Complex Components: Class components often become hard to understand due to unrelated stateful logic being scattered across different lifecycle methods, and related logic being split. Hooks allow you to organize code by what it's doing.
  • No 'this' Binding Issues: Hooks eliminate the confusion around 'this' context in JavaScript classes, making function components simpler to write and read.
  • Better Performance (Potentially): While not a primary goal, hooks can lead to less code and potentially more optimized rendering patterns in some scenarios.
  • Modern JavaScript: Align with the modern functional programming paradigm in JavaScript.

Common Built-in Hooks

React provides a few fundamental hooks that cover most use cases:

useState

Allows you to add React state to function components. It returns a pair: the current state value and a function that lets you update it.

javascript
import React, { useState } from 'react';

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

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

useEffect

Allows you to perform side effects in function components. It's a combination of componentDidMount, componentDidUpdate, and componentWillUnmount. Effects can be used for data fetching, subscriptions, manually changing the DOM, etc.

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

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

  useEffect(() => {
    document.title = `You clicked ${count} times`;
  }, [count]); // Rerun effect if count changes

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

useContext

Allows you to subscribe to React context without introducing nesting. It provides a way to pass data through the component tree without having to pass props down manually at every level.

javascript
import React, { useContext } from 'react';

const ThemeContext = React.createContext('light');

function ThemedButton() {
  const theme = useContext(ThemeContext);
  return <button style={{ background: theme === 'dark' ? 'black' : 'white', color: theme === 'dark' ? 'white' : 'black' }}>My {theme} Button</button>;
}

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

Rules of Hooks

There are two main rules to follow when using hooks, enforced by a linter plugin (eslint-plugin-react-hooks):

  • Only Call Hooks at the Top Level: Don't call Hooks inside loops, conditions, or nested functions. Hooks must be called in the same order on every render.
  • Only Call Hooks from React Functions: Call Hooks from React function components or from custom Hooks, not from regular JavaScript functions.

Benefits of Hooks

  • Simpler, Cleaner Code: Reduces boilerplate and improves readability compared to class components.
  • Enhanced Reusability: Custom hooks make it easy to share stateful logic across components.
  • Easier Testing: The isolated nature of hooks often makes logic easier to test.
  • Better DX (Developer Experience): Eliminates common pitfalls like this binding and complex lifecycle methods.