Github

10 Essential React Hooks You Should Know

Github

React has become a cornerstone of modern web development, and with it comes a set of powerful hooks that can simplify your code and enhance your applications. Hooks allow you to manage state, side effects, and other React features without writing class components. In this post, we'll explore ten essential hooks you should know to elevate your React skills.


1. useState

The useState hook allows you to add state to functional components. It returns a stateful value and a function to update it.typescriptSkopiuj kod

tsx

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

2. useEffect

The useEffect hook lets you perform side effects in functional components, such as data fetching or directly manipulating the DOM.

tsx

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

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

  useEffect(() => {
    fetch('https://api.example.com/data')
      .then(response => response.json())
      .then(data => setData(data));
  }, []); // Empty dependency array to run only once

  return <div>{data ? JSON.stringify(data) : 'Loading...'}</div>;
};

3. useContext

The useContext hook allows you to access the context directly without using a Consumer component. This makes it easier to manage global state.

tsx

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

const ThemeContext = createContext('light');

const ThemedComponent = () => {
  const theme = useContext(ThemeContext);
  
  return <div className={theme}>Current theme: {theme}</div>;
};

4. useReducer

The useReducer hook is an alternative to useState for managing complex state logic. It’s particularly useful when the next state depends on the previous one.

tsx

import React, { useReducer } from 'react';

type State = { count: number };
type Action = { type: 'increment' | 'decrement' };

const reducer = (state: State, action: Action): State => {
  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, { count: 0 });

  return (
    <div>
      <p>Count: {state.count}</p>
      <button onClick={() => dispatch({ type: 'increment' })}>Increment</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>Decrement</button>
    </div>
  );
};

5. useMemo

The useMemo hook helps optimize performance by memoizing the result of a computation. This can prevent expensive calculations on every render.

tsx

import React, { useMemo } from 'react';

const ExpensiveCalculation = ({ number }) => {
  const computedValue = useMemo(() => {
    // Expensive calculation
    return number * 2;
  }, [number]);

  return <div>Computed Value: {computedValue}</div>;
};

6. useCallback

The useCallback hook returns a memoized callback function, which is useful to avoid unnecessary re-renders when passing callbacks to child components.

tsx

import React, { useCallback } from 'react';

const Button = React.memo(({ onClick }) => (
  <button onClick={onClick}>Click me</button>
));

const ParentComponent = () => {
  const handleClick = useCallback(() => {
    console.log('Button clicked!');
  }, []);

  return <Button onClick={handleClick} />;
};

7. useRef

The useRef hook allows you to persist a mutable value across renders without causing a re-render. It's great for accessing DOM elements or keeping a mutable reference.

tsx

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

const Timer = () => {
  const timerId = useRef<NodeJS.Timeout | null>(null);

  useEffect(() => {
    timerId.current = setInterval(() => {
      console.log('Running interval...');
    }, 1000);

    return () => clearInterval(timerId.current!);
  }, []);

  return <div>Timer is running</div>;
};

8. useImperativeHandle

The useImperativeHandle hook customizes the instance value that is exposed to parent components when using ref. It works with forwardRef

tsx

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

const Child = forwardRef((props, ref) => {
  useImperativeHandle(ref, () => ({
    alertName: () => {
      alert('Hello from Child!');
    },
  }));

  return <div>Child Component</div>;
});

const Parent = () => {
  const childRef = useRef();

  const handleAlert = () => {
    if (childRef.current) {
      childRef.current.alertName();
    }
  };

  return (
    <div>
      <Child ref={childRef} />
      <button onClick={handleAlert}>Alert Child Name</button>
    </div>
  );
};

9. useLayoutEffect

The useLayoutEffect hook is similar to useEffect but it runs synchronously after all DOM mutations. It's useful for reading layout from the DOM and synchronously re-rendering.

tsx

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

const LayoutEffectExample = () => {
  const divRef = useRef<HTMLDivElement>(null);

  useLayoutEffect(() => {
    if (divRef.current) {
      console.log('Height of the div:', divRef.current.getBoundingClientRect().height);
    }
  }, []);

  return <div ref={divRef}>This is a div</div>;
};

10. useDebugValue

The useDebugValue hook is used to display a label for custom hooks in React DevTools. It's mainly for debugging purposes.

tsx

import { useDebugValue } from 'react';

function useMyCustomHook(value: number) {
  useDebugValue(value > 0 ? 'Positive' : 'Negative');
  // Custom logic here
}

Conclusion

Mastering React hooks involves understanding how and when to use them effectively. By integrating these ten essential hooks into your development toolkit, you can write cleaner, more efficient, and more maintainable code. Start implementing these hooks in your projects and watch your React skills soar!