#atom

Subtitle:

Centralized State Management for React Components Using Custom Store Factories


Core Idea:

The React Store Pattern creates a centralized state container with subscription capabilities that serves as a single source of truth for component trees, allowing components to access and update shared state without prop drilling or context overhead.


Key Principles:

  1. Centralized State Management:

    • Maintains all relevant state in a single store object
    • Provides controlled access to read and update state
  2. Subscription Model:

    • Components subscribe to specific state changes
    • Updates trigger selective component re-renders
  3. Encapsulated API:

    • Exposes limited methods for state interaction
    • Abstracts implementation details from consumers

Why It Matters:


How to Implement:

  1. Create Store Factory:

    • Implement a function that generates store instances
    • Use closures to maintain private state
  2. Subscription System:

    • Implement subscribe/unsubscribe mechanisms
    • Track listeners for each state slice
  3. Component Integration:

    • Hook into component lifecycle with useEffect
    • Clean up subscriptions when components unmount

Example:

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

// Generic createStore function
function createStore<T>(initialState: T) {
  // Private state
  let state = { ...initialState };
  const listeners: Record<string, Array<(value: any) => void>> = {};
  
  // Subscribe to changes for a specific key
  const subscribe = <K extends keyof T>(
    key: K, 
    callback: (value: T[K]) => void
  ) => {
    if (!listeners[key as string]) {
      listeners[key as string] = [];
    }
    listeners[key as string].push(callback);
    
    // Return unsubscribe function
    return () => {
      listeners[key as string] = listeners[key as string].filter(
        listener => listener !== callback
      );
    };
  };
  
  // Update a specific key in the store
  const update = <K extends keyof T>(key: K, value: T[K]) => {
    state[key] = value;
    
    // Notify all listeners for this key
    if (listeners[key as string]) {
      listeners[key as string].forEach(listener => listener(value));
    }
  };
  
  // Get current value for a key
  const get = <K extends keyof T>(key: K): T[K] => state[key];
  
  return { subscribe, update, get };
}

// Example usage with a component
function StoreConsumer({ store }) {
  const [count, setCount] = useState(store.get('count'));
  
  useEffect(() => {
    // Subscribe to count changes
    const unsubscribe = store.subscribe('count', setCount);
    
    // Clean up subscription when component unmounts
    return unsubscribe;
  }, [store]);
  
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => store.update('count', count + 1)}>
        Increment
      </button>
    </div>
  );
}

Connections:


References:

  1. Primary Source:

    • React Advanced Patterns documentation
  2. Additional Resources:

    • "State Management with React Hooks" by Kent C. Dodds
    • "Build Your Own React State Management" by Tanner Linsley

Tags:

#react #state-management #store #subscription #patterns #custom-hooks


Connections:


Sources: