Frontend State Management
Relevant source files
The following files were used as context for generating this wiki page:
The frontend application for SPK Kajek employs a hybrid state management strategy, primarily relying on React's built-in hooks (useState, useEffect) for local component state and leveraging the Context API for more global concerns like theming. This approach keeps component logic encapsulated while providing a centralized way to manage application-wide state such as user authentication and UI preferences.
Data fetching and server-side state are managed through side effects in components, which call an Axios-based API service to interact with the FastAPI backend. The state is then stored locally within the components that require it.
Sources: DASHBOARD_README.md, frontend/src/App.tsx
State Management Architecture
The application does not use a large-scale state management library like Redux or MobX. Instead, it combines several targeted strategies.
| Strategy | Mechanism | Scope | Key Files |
|---|---|---|---|
| Component State | useState, useEffect | State is localized to a single component or passed down as props. | AnalysisView.tsx, DashboardView.tsx |
| Authentication State | useState + Prop Drilling | Managed in the root App component and passed to the Layout. | App.tsx |
| UI/Layout State | useState + Prop Drilling | Manages active tabs, sidebar visibility, etc. | App.tsx, Layout.tsx, Sidebar.tsx |
| Theming | React Context API | Manages the application's theme (e.g., dark/light mode). | Layout.tsx |
Sources: DASHBOARD_README.md, frontend/src/App.tsx:21,70, frontend/src/components/Layout.tsx:15,22
Component & Prop Flow
The following diagram illustrates how state and props flow from the root App component down to the views and layout components.
This diagram shows that App.tsx is the source of truth for authentication and active view, passing this data down as props. Layout.tsx manages its own UI state for the sidebar.
Sources: frontend/src/App.tsx:21,70-72, frontend/src/components/Layout.tsx:15,44
Component-Level State
The majority of the application's state is managed locally within React components using the useState and useEffect hooks. This is particularly evident in complex views like AnalysisView.tsx.
Sources: frontend/src/components/AnalysisView.tsx, DASHBOARD_README.md
Example: AnalysisView State
The AnalysisView component manages all state related to the TOPSIS calculation, including user inputs, API results, and UI display modes.
| State Variable | Type | Description |
|---|---|---|
weights | WeightRequest | Stores the current values of the criteria weight sliders. |
results | any | Holds the ranking data returned from the /api/calculate endpoint. |
calculating | boolean | A flag to indicate when the API call is in progress, used for showing loaders. |
sensitivityData | any[] | Stores results from sensitivity analysis simulations. |
showSensitivity | boolean | Toggles the visibility of the sensitivity analysis chart. |
selectedVendors | string[] | An array of vendor names selected for the radar chart comparison. |
chartMode | '2d' | '3d' | Toggles between 2D (Recharts) and 3D (Three.js) chart visualizations. |
showSaveModal | boolean | Controls the visibility of the modal for saving analysis to history. |
showSuccessModal | boolean | Controls the visibility of the success confirmation modal after saving. |
Sources: frontend/src/components/AnalysisView.tsx:16-31
AnalysisView State Flow
The user's interactions within the AnalysisView component trigger state changes that, in turn, cause the UI to re-render with new data or in a new state.
This flow demonstrates how local state is used to create an interactive user experience, providing immediate feedback and handling asynchronous operations.
Sources: frontend/src/components/AnalysisView.tsx:33-44, 52-58
Global State
Authentication State
Authentication state is managed at the top level of the application in App.tsx. This ensures that the entire application is aware of the user's login status.
isAuthenticated(boolean): A flag that determines whether to render theLoginViewor the mainLayout.currentUser(object): Stores the logged-in user's profile information, which is passed down to theLayoutandSidebar.
Sources: frontend/src/App.tsx:49-50
The handleLogin and handleLogout functions in App.tsx are responsible for updating this state.
// frontend/src/App.tsx:52-66
const [isAuthenticated, setIsAuthenticated] = useState(false);
const [currentUser, setCurrentUser] = useState<any>(null);
const handleLogin = async (username: string, password: string) => {
try {
const response = await api.login(username, password);
setCurrentUser(response.user);
setIsAuthenticated(true);
} catch (error) {
throw error; // Let LoginView handle the error
}
};
const handleLogout = () => {
api.logout();
setCurrentUser(null);
setIsAuthenticated(false);
setActiveTab('dashboard');
};
The following sequence diagram illustrates the login process.
Theme State
The application theme is managed via React's Context API. While the ThemeContext.tsx file is not provided in the context, its usage is clear in Layout.tsx.
The Layout component consumes the context using a useTheme hook to get the current theme and a function to toggle it.
// frontend/src/components/Layout.tsx:15,22,81-87
const Layout: React.FC<LayoutProps> = ({...}) => {
const { theme, toggleTheme } = useTheme();
// ...
return (
// ...
<button
onClick={toggleTheme}
// ...
>
{theme === 'dark' ? <Sun /> : <Moon />}
</button>
// ...
);
}
This pattern allows any component wrapped in the ThemeProvider to access and modify the theme without prop drilling.
Sources: frontend/src/components/Layout.tsx:15,22,81-87, DASHBOARD_README.md
Data Fetching State
Data from the server is fetched within components using useEffect hooks. The fetched data is then stored in the component's local state using useState. The DashboardView.tsx component is a clear example of this pattern.
// frontend/src/components/DashboardView.tsx:15-28
const DashboardView: React.FC<DashboardViewProps> = ({ onNavigate }) => {
const [data, setData] = useState<DataItem[]>([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchData = async () => {
try {
const result = await api.getData();
setData(result);
} catch (error) {
console.error("Failed to fetch data", error);
} finally {
setLoading(false);
}
};
fetchData();
}, []);
// ...
This sequence diagram shows the flow of fetching initial vendor data for the dashboard.
Conclusion
The frontend state management for SPK Kajek is pragmatic and effective for its scope. It avoids the complexity of a global state library by relying on React's native hooks for most state management needs. Global state is used sparingly for authentication and theming, where it provides the most benefit. This architecture results in components that are largely self-contained, with clear data flows managed through props and context, making the system maintainable and easy to understand.