# State Management Pattern

For more details, see
https://www.notion.so/suno-ai/MobX-State-Management-176b01573ccf80b7b221c1ebaaef9fdb

## Architecture

### Root Store

- Located in `rootStore.ts`
- Acts as the central hub for all substores
- Uses a Proxy pattern to handle store access
- Provides access to shared resources (apiClient, queryClient, logger)

### Substores

Each substore is a MobX store that:

- Has access to the root store via `this.root`
- Can access other stores through the root store
- Uses `makeAutoObservable` for reactivity
- Follows a consistent pattern for state management

## Access Pattern Example (June 9/25)

### 1. Root Store Structure

```typescript
// rootStore.ts
import { enableStaticRendering } from 'mobx-react-lite';

// Enable static rendering for SSR
enableStaticRendering(typeof window === 'undefined');

// Define the type for all substores
type Substores = {
  session: SessionStore;
  clips: ClipsStore;
  // ... other stores
};

// Create the root store
function makeRootStore(apiClient, queryClient, logger) {
  let stores: Substores | null = null;

  // Create a proxy for the root store
  const rootStore = new Proxy(
    { apiClient, queryClient, logger },
    {
      get(target, prop) {
        // Handle direct properties
        if (prop in target) {
          return target[prop];
        }
        // Handle substores
        if (stores && prop in stores) {
          return stores[prop];
        }
        return undefined;
      },
    }
  );

  // Initialize all substores
  stores = {
    session: new SessionStore(rootStore),
    clips: new ClipsStore(rootStore),
    // ... other stores
  };

  return rootStore;
}
```

### 2. Substore Pattern

```typescript
// Example of a substore (e.g., sessionStore.ts)
import { makeAutoObservable } from 'mobx';

class SessionStore {
  constructor(rootStore) {
    this.root = rootStore; // Reference to root store
    makeAutoObservable(this);
  }

  // Observable state
  userId = null;
  user = null;

  // Actions
  setUser(user) {
    this.user = user;
    this.userId = user.id;
  }
}
```

### 3. React Context and Provider

```typescript
// chakraProviders.tsx
import { createContext, useContext } from 'react';
import { observer } from 'mobx-react-lite';

// Create context
export const StoreContext = createContext({} as RootStore);

// Custom hook to access stores
export function useStores() {
  return useContext(StoreContext);
}

// Provider component
export function Providers({ children }) {
  const [rootStore, setRootStore] = useState<RootStore | undefined>();

  useEffect(() => {
    setRootStore(makeRootStore(apiClient, queryClient, eventLogger));
  }, [queryClient]);

  return (
    <StoreContext.Provider value={rootStore}>
      {children}
    </StoreContext.Provider>
  );
}
```

### 4. Using Stores in Components

```typescript
// Example component
import { observer } from 'mobx-react-lite';
import { useStores } from './chakraProviders';

const MyComponent = observer(() => {
  const { session, clips } = useStores();

  return (
    <div>
      <h1>Welcome {session.user?.name}</h1>
      <div>
        {clips.items.map(clip => (
          <div key={clip.id}>{clip.title}</div>
        ))}
      </div>
    </div>
  );
});
```
