React Hooks: A Comprehensive Guide to Built-in React Hooks
Tags: javascript, beginners, react, hooks
Published: 2023-07-27 23:37:22

# Introduction

I've been using React for about two years, so I thought I'd review Hooks once here, so I wrote an article on how to use the basics of Hooks. React Hooks have revolutionized the way developers build dynamic components in React applications. With Hooks, managing state, sharing data, handling effects, and enhancing performance has become more intuitive and efficient. In this all-inclusive guide, we will delve into the world of React Hooks, exploring essential ones like useState, useReducer, useContext, useRef, useEffect, useMemo, and useCallback, to unleash their full potential in your projects.


# 1. State Hooks
 - useState

The useState Hook enables functional components to manage state effortlessly, allowing easy initialization and updates of state variables.
```react
import React, { useState } from 'react';

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

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

- useReducer

The useReducer Hooks is ideal for managing complex state logic, utilizing a reducer function and providing a more advanced alternative to useState.
```react
import React, { useReducer } from 'react';

const initialState = { count: 0 };

const reducer = (state, action) => {
  switch (action.type) {
    case 'INCREMENT':
      return { count: state.count + 1 };
    case 'DECREMENT':
      return { count: state.count - 1 };
    default:
      return state;
  }
};

const 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>
  );
};
```


# 2. Context Hooks
- useContext

The useContext Hook provides seamless access to data and functions from a React context, eliminating the need for multiple context consumers.
```react
import React, { useContext } from 'react';

const UserContext = React.createContext();

const App = () => {
  const user = { name: 'John', age: 30 };
  return (
    <UserContext.Provider value={user}>
      <UserProfile />
    </UserContext.Provider>
  );
};


const UserProfile = () => {
  const user = useContext(UserContext);
  return <p>Name: {user.name}, Age: {user.age}</p>;
};
```


# 3. Ref Hooks
- useRef

The useRef Hook facilitates handling references to DOM elements or values that persist across renders, helping to maintain data between function calls. 
```react
import React, { useRef } from 'react';

const TextInput = () => {
  const inputRef = useRef(null); // returns { current: null }

  const handleFocus = () => {
    inputRef.current.focus();
  };

  return (
    <div>
      <input ref={inputRef} type="text" />
      <button onClick={handleFocus}>Focus Input</button>
    </div>
  );
};
```


- useImperativeHandle (This is rarely used)

The useImperativeHandle Hook allows customization of the instance value that is exposed to parent components when using the ref prop.
```react
import React, { useRef, useImperativeHandle, forwardRef } from 'react';

const CustomInput = forwardRef((props, ref) => {
  const inputRef = useRef();

  useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current.focus();
    },
  }));

  return <input ref={inputRef} type="text" />;
});

  const ParentComponent = () => {
  const customInputRef = useRef();

  const handleFocus = () => {
    customInputRef.current.focus();
  };

  return (
    <div>
      <CustomInput ref={customInputRef} />
      <button onClick={handleFocus}>Focus Custom Input</button>
    </div>
  );
};
```


# 4. Effect Hooks
- useEffect

The useEffect Hook handles side effects like data fetching subscriptions, and DOM manipulation, seamlessly integrating with functional components.
```react
import React, { useEffect, useState } from 'react';

const DataFetching = () => {
  const [data, setData] = useState([]);

  useEffect(() => {
    fetch('https://api.example.com/data')
      .then((response) => response.json())
      .then((data) => setData(data));
  }, []);

  return (
    <div>
      {data.map((item) => (
        <p key={item.id}>{item.name}</p>
      ))}
    </div>
  );
};
```

- useLayoutEffect

The useLayoutEffect Hook is similar to useEffect, but it runs synchronously after all DOM mutations, ensuring immediate updates.
```react
import React, { useState, useLayoutEffect } from 'react';

const ResizeObserver = () => {
  const [width, setWidth] = useState(0);

  useLayoutEffect(() => {
    const handleResize = () => {
      setWidth(window.innerWidth);
    };

    window.addEventListener('resize', handleResize);
    handleResize();

    return () => window.removeEventListener('resize', handleResize);
  }, []);

  return <p>Window Width: {width}</p>;
};
```


- useInsertionEffect (For CSS-in-JS library authors)

The useInsertionEffect Hook is used for styling transitions during the insertion of new elements into the DOM.
```react
import React, { useState, useInsertionEffect } from 'react';

const List = () => {
  const [items, setItems] = useState([]);

  useInsertionEffect(() => {
    // Add transition styles for new items
  });

  const handleAddItem = () => {
    setItems([...items, { id: items.length + 1, name: `Item ${items.length + 1}` }]);
  };

  return (
    <div>
      <button onClick={handleAddItem}>Add Item</button>
      <ul>
        {items.map((item) => (
          <li key={item.id}>{item.name}</li>
        ))}
      </ul>
    </div>
  );
};
```


# 5. Performance Hooks
- useMemo

The useMemo Hook efficiently memorizes the result of a function, preventing expensive recalculations and optimizing rendering performance.
```react
import React, { useMemo, useState } from 'react';

const Fibonacci = ({ n }) => {
  const fib = useMemo(() => {
    if (n <= 1) return n;
    return Fibonacci({ n: n - 1 }) + Fibonacci({ n: n - 2 });
  }, [n]);

  return <p>Fibonacci({n}): {fib}</p>;
};
```

- useCallback

The useCallback Hook memorizes a callback function, preventing unnecessary recreations and optimizing performance in child components.
```react
import React, { useCallback, useState } from 'react';

const 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>
  );
};
```

- useTransition

The useTransition Hook allows concurrent rendering of multiple components, enhancing performance for complex user interfaces.
```react
import React, { useTransition, useState } from 'react';

const TransitionExample = () => {
  const [isPending, startTransition] = useTransition({ timeoutMs: 500 });

  const handleButtonClick = () => {
    startTransition(() => {
      // Perform state updates or fetch data
    });
  };

  return (
    <div>
      <button disabled={isPending} onClick={handleButtonClick}>
        {isPending ? 'Loading...' : 'Start Transition'}
      </button>
    </div>
  );
};
```

- useDeferredValue

The useDeferredValue Hook defers the rendering of a value, optimizing performance for asynchronous updates.
```react
import React, { useDeferredValue, useState } from 'react';

const AsyncValue = () => {
  const [isPending, setIsPending] = useState(true);
  const deferredValue = useDeferredValue(isPending);

  // Simulate async data fetching
  setTimeout(() => {
    setIsPending(false);
  }, 2000);

  return <p>{deferredValue ? 'Fetching data...' : 'Data loaded'}</p>;
};
```


# 6. Other Hooks
- useDebugValue

The useDebugValue Hook enables custom labeling of custom hooks in React DevTools for easier debugging.
```react
import { useDebugValue, useState } from 'react';

const useCustomHook = () => {
  const [count, setCount] = useState(0);
  useDebugValue(`CustomHook: ${count}`);
  return [count, setCount];
};
```

- useId

The useId Hook generates unique IDs that persist across renders, useful for labeling from elements or other components.
```react
import { useId } from 'react';

const UniqueComponent = () => {
  const uniqueId = useId();

  return <p>{`Element ID: ${uniqueId}`}</p>;
};
```

- useSyncExternalStore

The useSyncExternalStore Hook enables synchronization between local and external data stores for maintaining consistent data flow.
```react
import { useSyncExternalStore } from 'react';

const DataSync = () => {
  const [localData, setLocalData] = useState([]);
  useSyncExternalStore('https://api.example.com/data', setLocalData);

  return (
    <div>
      {localData.map((item) => (
        <p key={item.id}>{item.name}</p>
      ))}
    </div>
  );
};
```


# Conclusion

React Hooks offers a wide array of powerful tools for state management, context handling, effect management, and performance optimization. By leveraging the versatility of these hooks, developers can create efficient and maintainable React applications that deliver seamless user experiences. Remember to explore the official React documentation and community resources to discover even more Hooks and enhance your React development skills. Happy coding with React!