Dung (Donny) Nguyen

Senior Software Engineer

React Hooks

React hooks are functions that let us use React state and lifecycle features in functional components, which were previously only available in class components. Introduced in React 16.8, hooks enable us to manage state and side effects in a more straightforward and reusable manner. Here’s a closer look at what hooks are and why they are so useful:

Key Hooks and Their Uses

  1. useState:
    • Manages state in functional components.
    • Returns a state variable and a function to update it.
    • Example:
      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>
        );
      }
      
      export default Counter;
      
  2. useEffect:
    • Handles side effects such as data fetching, subscriptions, and manually changing the DOM.
    • Runs after every render by default but can be controlled with dependencies.
    • Example:
      import React, { useState, useEffect } from 'react';
      
      function DataFetcher() {
        const [data, setData] = useState(null);
      
        useEffect(() => {
          fetch('https://api.example.com/data')
            .then(response => response.json())
            .then(data => setData(data));
        }, []); // Empty array means this effect runs once on mount
      
        return <div>{data ? data.title : 'Loading...'}</div>;
      }
      
      export default DataFetcher;
      
  3. useContext:
    • Consumes context values set by React.createContext.
    • Simplifies the process of passing data deeply through the component tree.
    • Example:
      import React, { createContext, useContext } from 'react';
      
      const UserContext = createContext();
      
      function UserDisplay() {
        const user = useContext(UserContext);
        return <div>Username: {user.name}</div>;
      }
      
      function App() {
        const user = { name: 'Alice' };
      
        return (
          <UserContext.Provider value={user}>
            <UserDisplay />
          </UserContext.Provider>
        );
      }
      
      export default App;
      
  4. useReducer:
    • Manages complex state logic using reducers.
    • Useful when the state logic is too complex for useState or when the next state depends on the previous state.
    • Example:
      import React, { useReducer } from 'react';
      
      const initialState = { count: 0 };
      
      function reducer(state, action) {
        switch (action.type) {
          case 'increment':
            return { count: state.count + 1 };
          case 'decrement':
            return { count: state.count - 1 };
          default:
            throw new Error();
        }
      }
      
      function Counter() {
        const [state, dispatch] = useReducer(reducer, initialState);
      
        return (
          <div>
            <p>Count: {state.count}</p>
            <button onClick={() => dispatch({ type: 'increment' })}>Increment</button>
            <button onClick={() => dispatch({ type: 'decrement' })}>Decrement</button>
          </div>
        );
      }
      
      export default Counter;
      
  5. useRef:
    • Provides a way to access and manipulate DOM elements directly.
    • Can also be used to persist values across renders without causing a re-render.
    • Example:
      import React, { useRef, useEffect } from 'react';
      
      function TextInputWithFocusButton() {
        const inputEl = useRef(null);
      
        const onButtonClick = () => {
          // Access the DOM node via inputEl.current
          inputEl.current.focus();
        };
      
        return (
          <div>
            <input ref={inputEl} type="text" />
            <button onClick={onButtonClick}>Focus the input</button>
          </div>
        );
      }
      
      export default TextInputWithFocusButton;
      

Additional Hooks

Why Use Hooks?

React hooks bring the power of React’s state and lifecycle methods to functional components, making them more versatile and easier to work with. This has significantly improved the way developers write and manage React applications.