State Management
Relevant source files
The following files were used as context for generating this wiki page:
The ElmecV2 application employs a hybrid state management strategy, combining a centralized global store with feature-specific contexts. This approach leverages Zustand for managing global application state and React's Context API for localized, modular state, particularly for features involving authentication and real-time data. This dual strategy provides both a scalable global state solution and encapsulated logic for complex, self-contained modules.
Sources: README.md, store/index.ts, contexts/AuthContext.tsx, contexts/ChatContext.tsx
This diagram illustrates the high-level state management architecture.
Core Technologies
The project utilizes two primary technologies for state management:
| Technology | Scope | Use Case |
|---|---|---|
| Zustand | Global | Manages application-wide state that is shared across many components, such as calculator sessions. |
| React Context API | Feature-Specific / Localized | Manages state that is tightly coupled to a specific feature or component tree, like user authentication and real-time chat. |
Sources: README.md, store/index.ts, contexts/AuthContext.tsx, contexts/ChatContext.tsx
Global State with Zustand
Zustand is used for a minimal, fast, and scalable global state. The implementation is modular, using "slices" to separate concerns.
Sources: store/index.ts, store/calculatorSlice.ts
Store Setup
The main store is configured in store/index.ts. It combines multiple state slices into a single global store. The project is set up to use Redux DevTools for easier debugging in development environments.
The following diagram shows how different slices are combined to form the main Zustand store.
Sources: store/index.ts:7-19
The core of the store is created using Zustand's create function, combined with middleware for Redux DevTools integration.
// store/index.ts:7-19
import { create } from 'zustand';
import { devtools } from 'zustand/middleware';
import { calculatorSlice, CalculatorState } from './calculatorSlice';
// Define the shape of the entire state
export type AppState = CalculatorState; // & OtherState...
export const useStore = create<AppState>()(
devtools(
(...a) => ({
...calculatorSlice(...a),
// ...other slices can be added here
}),
{ name: 'ElmecV2ZustandStore' }
)
);
Sources: store/index.ts:7-19
Calculator Slice
The calculatorSlice.ts file provides a concrete example of a Zustand slice. It manages the state for the integrated Fresado and Barrenado calculators, including input values, results, and session history.
The state is designed to persist calculator sessions, allowing users to resume their work.
| Action | Description |
|---|---|
setFresadoValue | Updates a specific field in the Fresado calculator form. |
calculateFresado | Performs the Fresado calculation based on current inputs and updates the result. |
setBarrenadoValue | Updates a specific field in the Barrenado calculator form. |
calculateBarrenado | Performs the Barrenado calculation and updates the result. |
saveSession | Saves the current state of a calculator (Fresado or Barrenado) to the session history. |
loadSession | Loads a saved session into the active calculator state. |
deleteSession | Removes a specific session from the history. |
clearHistory | Clears all saved calculator sessions. |
Sources: store/calculatorSlice.ts:38-118
Accessing the Store
To ensure type safety and provide a standard way to interact with the store, the project defines custom typed hooks in store/hooks.ts. While Zustand's useStore can be used directly, the README.md mentions Zustand and this file structure is typical for Redux Toolkit, which might have been used previously or alongside. The provided files store/index.ts and store/hooks.ts do not define useAppDispatch or useAppSelector but are structured in a way that suggests jejich existence in a larger context. The useStore hook from store/index.ts is the primary way to access the Zustand store.
// Example of using the store in a component
import { useStore } from '@/store';
const MyComponent = () => {
const fresadoResult = useStore((state) => state.fresado.result);
const calculateFresado = useStore((state) => state.calculateFresado);
// ...
}
Sources: store/index.ts:11
Feature-Specific State with React Context
For state that is specific to a particular feature, the application uses React's Context API. This encapsulates state logic and prevents bloating the global store.
Authentication Context
The AuthContext.tsx manages all aspects of user authentication, session, and profile data. It acts as a single source of truth for the user's authentication status throughout the application.
The context provider fetches the user session from Supabase and makes the user data, session information, and authentication status available to all child components.
This sequence diagram shows the flow when a user logs in.
Sources: contexts/AuthContext.tsx
The AuthProvider exposes the following values to its children:
| Value | Type | Description |
|---|---|---|
session | Session | null | The current Supabase session object. |
user | User | null | The authenticated user's profile data. |
isAuthenticated | boolean | A flag indicating if the user is currently authenticated. |
isLoading | boolean | A flag indicating if the initial session check is in progress. |
isAdmin | boolean | A flag indicating if the user has an 'admin' role. |
signOut | () => void | A function to log the user out. |
Sources: contexts/AuthContext.tsx:16-23, 71-77
Chat Context
A more complex example of React Context is ChatContext.tsx. It manages the real-time state for the chat module, including fetching chat rooms, sending/receiving messages, and handling Supabase real-time subscriptions.
This context is responsible for:
- Subscribing to new messages in a chat room via Supabase Realtime.
- Handling optimistic UI updates for sent messages.
- Managing the state of all chat rooms and the messages within the active room.
- Implementing "typing..." indicators using Supabase's presence feature.
This diagram shows how a new message is received in real-time.
Sources: contexts/ChatContext.tsx:191-220
The ChatProvider is a high-level component that wraps parts of the application needing access to chat functionality, providing them with functions to send messages, create rooms, and access message history.
Sources: contexts/ChatContext.tsx
Conclusion
The state management architecture in ElmecV2 is pragmatic and well-structured. It uses Zustand for simple, shared global state, keeping the global namespace clean and performance high. For complex, feature-rich modules like Authentication and Chat, it leverages the React Context API to encapsulate state and logic, promoting modularity and preventing the global store from becoming a bottleneck. This hybrid approach provides a scalable and maintainable foundation for the application's state.