React

Deep Dive into React Hooks: Beyond the Basics

10 min read
Mahmoud Amr
Mahmoud Amr
Deep Dive into React Hooks: Beyond the Basics

Deep Dive into React Hooks: Beyond the Basics

Master React Hooks with advanced patterns and real-world examples that will take your React applications to the next level.

Custom Hooks

Creating reusable logic with custom hooks:

function useLocalStorage<T>(key: string, initialValue: T) {
  const [storedValue, setStoredValue] = useState<T>(() => {
    try {
      const item = window.localStorage.getItem(key);
      return item ? JSON.parse(item) : initialValue;
    } catch (error) {
      console.error(error);
      return initialValue;
    }
  });

  const setValue = (value: T | ((val: T) => T)) => {
    try {
      const valueToStore = value instanceof Function ? value(storedValue) : value;
      setStoredValue(valueToStore);
      window.localStorage.setItem(key, JSON.stringify(valueToStore));
    } catch (error) {
      console.error(error);
    }
  };

  return [storedValue, setValue] as const;
}

useEffect Best Practices

Optimizing dependencies and cleanup:

function useEventListener(
  eventName: string,
  handler: (event: Event) => void,
  element = window
) {
  const savedHandler = useRef(handler);

  useEffect(() => {
    savedHandler.current = handler;
  }, [handler]);

  useEffect(() => {
    const isSupported = element && element.addEventListener;
    if (!isSupported) return;

    const eventListener = (event: Event) => savedHandler.current(event);
    element.addEventListener(eventName, eventListener);

    return () => {
      element.removeEventListener(eventName, eventListener);
    };
  }, [eventName, element]);
}

Advanced Patterns

The Reducer Pattern

Using useReducer for complex state:

type State = {
  count: number;
  isLoading: boolean;
  error: string | null;
};

type Action =
  | { type: 'INCREMENT' }
  | { type: 'DECREMENT' }
  | { type: 'SET_LOADING'; payload: boolean }
  | { type: 'SET_ERROR'; payload: string };

function reducer(state: State, action: Action): State {
  switch (action.type) {
    case 'INCREMENT':
      return { ...state, count: state.count + 1 };
    case 'DECREMENT':
      return { ...state, count: state.count - 1 };
    case 'SET_LOADING':
      return { ...state, isLoading: action.payload };
    case 'SET_ERROR':
      return { ...state, error: action.payload };
    default:
      return state;
  }
}

Performance Optimization

Tips for optimizing hooks:

  1. Use useMemo for expensive calculations
  2. Implement useCallback for function memoization
  3. Avoid unnecessary re-renders
  4. Properly structure dependencies

Conclusion

Understanding these advanced hook patterns will help you write more efficient and maintainable React applications.

ReactHooksJavaScriptWeb Development