DEV Community

Cover image for Essential Hooks for Every Developer
Fadoua Rasmouki
Fadoua Rasmouki

Posted on

Essential Hooks for Every Developer

Introduction - What is a React Hook?

A React Hook is a special function that lets you "hook into" React features like state and lifecycle methods, enabling functional components to manage state and side effects.

Now, you've decided to build a React app, leveraging the power of React hooks. With numerous hooks available, it can be challenging to know which ones to use.

Let's explore the essential hooks, understand their functions, and see some concise examples to get you started:

State Management Hooks

useState

The useState hook is fundamental for managing state and rendering components upon state changes.

import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);
  return (
    <div>
      <p>{count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

useReducer

The useReducer hook is ideal for handling more complex state logic.

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>{state.count}</p>
      <button onClick={() => dispatch({ type: 'increment' })}>Increment</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>Decrement</button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Effect Hooks

useEffect

Effect hooks allow you to perform side effects, such as data fetching or DOM manipulation.

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

function Example() {
  const [count, setCount] = useState(0);
  useEffect(() => {
    document.title = `Count: ${count}`;
  }, [count]);

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

useLayoutEffect

useLayoutEffect runs synchronously after all DOM mutations, useful for operations that need to occur before the browser repaints.

import React, { useLayoutEffect, useRef } from 'react';

function LayoutEffectExample() {
  const ref = useRef();
  useLayoutEffect(() => {
    console.log(ref.current.getBoundingClientRect());
  }, []);
  return <div ref={ref}>Measure my dimensions</div>;
}
Enter fullscreen mode Exit fullscreen mode

Ref Hooks

useRef

The useRef hook allows you to persist values across renders without causing a re-render.

import React, { useRef } from 'react';

function TextInputWithFocusButton() {
  const inputEl = useRef(null);
  const onButtonClick = () => {
    inputEl.current.focus();
  };

  return (
    <div>
      <input ref={inputEl} type="text" />
      <button onClick={onButtonClick}>Focus the input</button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

useImperativeHandle

useImperativeHandle customizes the instance value that is exposed when using ref in parent components.

import React, { useImperativeHandle, useRef, forwardRef } from 'react';

const FancyInput = forwardRef((props, ref) => {
  const inputRef = useRef();
  useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current.focus();
    }
  }));
  return <input ref={inputRef} />;
});

function Parent() {
  const inputRef = useRef();
  return (
    <div>
      <FancyInput ref={inputRef} />
      <button onClick={() => inputRef.current.focus()}>Focus the input</button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Performance Hooks

useMemo

useMemo memoizes expensive calculations, recomputing the cached value only when its dependencies change.

import React, { useMemo } from 'react';

function ExpensiveCalculationComponent({ num }) {
  const result = useMemo(() => num * 2, [num]);
  return <div>Result: {result}</div>;
}
Enter fullscreen mode Exit fullscreen mode

useCallback

useCallback memoizes callback functions, preventing unnecessary re-creations on each render.

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

function Button({ onClick }) {
  return <button onClick={onClick}>Click me</button>;
}

function App() {
  const [count, setCount] = useState(0);
  const handleClick = useCallback(() => setCount(count + 1), [count]);
  return (
    <div>
      <p>{count}</p>
      <Button onClick={handleClick} />
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Context Hooks

useContext

useContext accesses values from a context provider.

import React, { useContext } from 'react';

const MyContext = React.createContext();

function Display() {
  const value = useContext(MyContext);
  return <div>{value}</div>;
}

function App() {
  return (
    <MyContext.Provider value="Hello, World!">
      <Display />
    </MyContext.Provider>
  );
}
Enter fullscreen mode Exit fullscreen mode

Transition Hooks

useTransition

useTransition marks state updates as non-urgent, improving user experience by deferring heavy computations.

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

function FilterList({ items }) {
  const [filter, setFilter] = useState('');
  const [isPending, startTransition] = useTransition();
  const filteredItems = items.filter((item) =>
    item.toLowerCase().includes(filter.toLowerCase())
  );

  return (
    <div>
      <input
        type="text"
        value={filter}
        onChange={(e) => {
          startTransition(() => setFilter(e.target.value));
        }}
      />
      {isPending ? <p>Loading...</p> : filteredItems.map((item) => <p key={item}>{item}</p>)}
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

useDeferredValue

useDeferredValue defers a value update to maintain responsiveness.

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

function DeferredList({ items }) {
  const [filter, setFilter] = useState('');
  const deferredFilter = useDeferredValue(filter);
  const filteredItems = items.filter((item) =>
    item.toLowerCase().includes(deferredFilter.toLowerCase())
  );

  return (
    <div>
      <input type="text" value={filter} onChange={(e) => setFilter(e.target.value)} />
      {filteredItems.map((item) => (
        <p key={item}>{item}</p>
      ))}
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

React hooks provide a powerful and flexible way to manage state, handle side effects, and optimize performance in your React applications. By understanding and utilizing these essential hooks, you can build more efficient and maintainable React apps. For a deeper dive into all things React, consider exploring comprehensive resources and bootcamps that offer interactive challenges, videos, and cheat sheets.

Top comments (0)