Farzad Yousefzadeh
  • About
  • Appearances
  • Blog
  • Mentorship

Uset `set` as a state primitive in useState

November 17, 2024
Check out all posts

When working with React, we sometimes need to use a Set as our primary data structure. However, this presents a challenge because React is designed around immutable state updates, while Set (and Map) are inherently mutable data structures. This creates a fundamental mismatch: React expects us to create new instances when updating state, but Set methods like add() and delete() modify the existing instance. The solution is to create an abstraction layer that:

Preserves the efficiency and functionality of Set as the underlying data structure Provides an immutable interface that aligns with React's state update patterns Maintains referential integrity for React's change detection

In simpler terms, we need to wrap our mutable Set operations in a way that makes them appear immutable to React, while still leveraging the Set data structure's unique properties and performance characteristics.

useSet custom hook

const useSet = <T>(initialSet: Set<T> = new Set<T>()) => {
  const [state, _setState] = useState<Set<T>>(initialSet);
  const add = useCallback((value: T) => {
    _setState((prev) => {
      const newSet = new Set(prev);
      newSet.add(value);
      return newSet;
    });
  }, []);
  const clear = useCallback(() => {
    _setState(new Set());
  }, []);
  // ... other Set methods
  return [state, add, clear, ...otherMethods] as const;
};

The materials of this website are licensed under The Creative Commons