DEV Community

Cover image for React Hooks Essentials
Ryoichi Homma
Ryoichi Homma

Posted on • Edited on

React Hooks Essentials

Concept Highlights:

  1. What is Hooks?
  2. Why Use Hooks?
  3. useState
  4. useEffect
  5. useReducer
  6. useRef
  7. Custom Hooks
  8. Toggle with dispatch
  9. What is UseHooks.com?
  10. useCallback

1. What is Hooks and Why

In React, Hooks are special functions that allow you to use state and other React features in functional components, without needing to convert them into class components. Introduced in React 16.8, hooks make it easier to reuse logic between components, handle state management, and manage side effects like data fetching or subscriptions, all within functional components.

2. Why Use Hooks?

  • Cleaner Code: Hooks simplify the structure of your components by allowing you to manage state and side effects directly in functional components.
  • Reusability: Custom hooks allow you to reuse stateful logic without duplicating code or restructuring components.
  • Functional Components: Hooks enable you to write functional components that are just as powerful as class components, leading to a more consistent codebase.

3. useState

The useState hook is fundamental for managing state in functional components. Instead of using class components with this.setState(), you can manage state seamlessly with this hook.

Syntax:

const [state, setState] = useState(initialState);
Enter fullscreen mode Exit fullscreen mode

e.g.) In this example, it initializes count with a value of 0 and use the setCount function to update it when the button is clicked.

import React, { useState } from 'react';

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

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

4. useEffect

The useEffect hook allows you to handle side effects in your components, like fetching data, updating the DOM, or subscribing to events.

Syntax:

useEffect(() => {
  // Side effect logic
  return () => {
    // Cleanup
  };
}, [dependencies]);
Enter fullscreen mode Exit fullscreen mode

e.g.) In this example, useEffect fetches data from an API when the component mounts. The empty array [] as a second argument ensures the effect runs only once (like componentDidMount).

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));
  }, []);

  return (
    <div>
      {data ? <p>{data.title}</p> : <p>Loading...</p>}
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

5. useReducer

When your state logic becomes more complex, consider using useReducer instead of useState. It’s similar to Redux but at the component level. You can use it to manage state transitions based on action types.

Syntax:

const [state, dispatch] = useReducer(reducer, initialState);
Enter fullscreen mode Exit fullscreen mode

e.g.) In this example, useReducer handles two actions: increment and decrement. You use dispatch to trigger state updates based on these actions.

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:
      return state;
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <div>
      <p>Count: {state.count}</p>
      <button onClick={() => dispatch({ type: 'increment' })}>+</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

6. useRef

The useRef hook provides a way to directly access and manipulate DOM elements or store mutable values across renders without causing re-renders.

Syntax:

const myRef = useRef(initialValue);
Enter fullscreen mode Exit fullscreen mode

e.g.) In this example, useRef allows direct access to the input filed, enabling to programmatically focus it when the button is clicked.

import React, { useRef } from 'react';

function InputFocus() {
  const inputRef = useRef(null);

  const handleFocus = () => {
    inputRef.current.focus();
  };
  return (
    <div>
      <input ref={inputRef} type="text" />
      <button onClick={handleFocus}>Focus Input</button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

7. Custom Hooks

One of the powerful aspects of hooks is that you can create your custom hooks to encapsulate and reuse logic across components. Custom hooks start with use and are just regular JavaScript functions that can use other hooks.

e.g.) In this example, the useFetch hook handles data fetching logic and can be reused in multiple components.

import { useState, useEffect } from 'react';

function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetch(url)
      .then(response => response.json())
      .then(data => {
        setData(data);
        setLoading(false);
      });
  }, [url]);

  return { data, loading };
}

function App() {
  const { data, loading } = useFetch('https://api.example.com/data');

  return <div>{loading ? <p>Loading...</p> : <p>{data.title}</p>}</div>;
}
Enter fullscreen mode Exit fullscreen mode

8. Toggle with dispatch

The dispatch method can be used in combination with useReducer to create toggle states, which is helpful for handling components like modals, dropdowns, or toggling themes.

e.g.) The toggle action in the dispatch method switches the isVisible state between true and false, which in turn toggles the visibility of content.

import React, { useReducer } from 'react';

const initialState = { isVisible: false };

function reducer(state, action) {
  switch (action.type) {
    case 'toggle':
      return { isVisible: !state.isVisible };
    default:
      return state;
  }
}

function ToggleComponent() {
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <div>
      <button onClick={() => dispatch({ type: 'toggle' })}>
        {state.isVisible ? 'Hide' : 'Show'} Details
      </button>
      {state.isVisible && <p>Here are the details...</p>}
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

9. What is UseHooks.com?

If you're interested in diving deeper into hooks or exploring useful custom hooks for your projects, I highly recommend checking out UseHooks.com. It’s a fantastic resource with tons of practical custom hooks that you can use and learn from.

10. useCallback

The useCallback hook is used to memorize functions in React. This is especially useful when passing callbacks to child components since it prevents the function from being recreated on every render.

Syntax:

const memoizedCallback = useCallback(() => {
  doSomething(a, b);
}, [a, b]);
Enter fullscreen mode Exit fullscreen mode

e.g.) In this example, the increment function is memorized using useCallback, so it's not recreated on every render, which helps improve performance in certain scenarios.

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

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

  const increment = useCallback(() => {
    setCount(prevCount => prevCount + 1);
  }, []);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)