mirror of
https://dev.azure.com/tstanciu94/ReverseProxy/_git/ReverseProxy_Frontend
synced 2025-10-03 16:49:04 +03:00
- feat: Add session management components and improve system overview - feat: Update dependencies and replace react-flags with react-country-flag - Update dependencies in package.json: reintroduce react-dom and upgrade redux to version 5.0.1 - refactor: update chatbot implementation and dependencies - refactor: migrate to Redux Toolkit and update dependencies - feat: enhance ReactCountryFlag component with SVG support - refactor: remove Bootstrap dependency and update Node engine requirement; add LabelValue component for better UI consistency - refactor: enhance LabelValue component usage in ServerSummary for improved readability and tooltip support - refactor: replace inline text with LabelValue component in ActiveSessionSummary and SessionSummary for improved consistency and readability - refactor: update components to use LabelValue for improved consistency and readability - refactor: optimize LabelValue component for improved readability and structure - refactor: improve code readability in SessionForwardsComponent by standardizing arrow function syntax and adjusting styling properties
8.6 KiB
8.6 KiB
Redux to RTK Upgrade Plan
Current State Analysis
✅ What's Working Well
- Modular Organization: Reducers organized by features (server, sessions, chatbot, etc.)
- Redux Toolkit Integration: Using
@reduxjs/toolkit
andconfigureStore
- Consistent Loading States: Pattern for
loading/loaded
on each entity - TypeScript Integration: Well-defined types for actions and state
Current Architecture Pattern
features/
├── server/
│ ├── actionTypes.ts - Action type constants
│ ├── actionCreators.ts - Async action creators with thunks
│ ├── reducer.ts - State management logic
│ └── api.ts - API calls
└── [other features...]
Upgrade Opportunities
1. Redux Toolkit Slices (Major Improvement)
Current approach uses classic Redux pattern with separate files:
// actionTypes.ts
export const LOAD_SERVER_DATA_SUCCESS = "LOAD_SERVER_DATA_SUCCESS" as const;
// actionCreators.ts
export function loadServerData() {
return async function(dispatch: Dispatch): Promise<void> {
try {
const data = await dispatch(sendHttpRequest(api.getServerData()) as any);
dispatch({ type: types.LOAD_SERVER_DATA_SUCCESS, payload: data });
} catch (error) {
throw error;
}
};
}
// reducer.ts
export default function serverReducer(state: ServerState = initialState.server, action: ServerAction): ServerState {
switch (action.type) {
case types.LOAD_SERVER_DATA_SUCCESS:
return { ...state, data: { ...action.payload, loading: false, loaded: true } };
default:
return state;
}
}
Recommended RTK Slice approach:
// serverSlice.ts
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
export const loadServerData = createAsyncThunk(
'server/loadData',
async () => {
return await api.getServerData();
}
);
const serverSlice = createSlice({
name: 'server',
initialState: {
data: { loading: false, loaded: false },
activeSession: { loading: false, loaded: false }
},
reducers: {
// Synchronous actions
clearServerData: (state) => {
state.data = { loading: false, loaded: false };
}
},
extraReducers: (builder) => {
builder
.addCase(loadServerData.pending, (state) => {
state.data.loading = true;
})
.addCase(loadServerData.fulfilled, (state, action) => {
state.data = { ...action.payload, loading: false, loaded: true };
})
.addCase(loadServerData.rejected, (state) => {
state.data.loading = false;
});
}
});
export const { clearServerData } = serverSlice.actions;
export default serverSlice.reducer;
Benefits:
- 70% less boilerplate code
- Automatic action creators
- Built-in loading/error handling
- Immer integration (direct state mutations)
- Better TypeScript inference
2. RTK Query for API Management
Current API pattern:
// Separate API calls, manual caching, manual loading states
export function loadServerData() {
return async function(dispatch: Dispatch): Promise<void> {
try {
const data = await dispatch(sendHttpRequest(api.getServerData()) as any);
dispatch({ type: types.LOAD_SERVER_DATA_SUCCESS, payload: data });
} catch (error) {
throw error;
}
};
}
RTK Query approach:
// api/serverApi.ts
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
export const serverApi = createApi({
reducerPath: 'serverApi',
baseQuery: fetchBaseQuery({
baseUrl: '/api/',
prepareHeaders: (headers) => {
// Add auth headers, content-type, etc.
return headers;
},
}),
tagTypes: ['ServerData'],
endpoints: (builder) => ({
getServerData: builder.query<ServerData, void>({
query: () => 'server',
providesTags: ['ServerData'],
}),
getActiveSession: builder.query<ActiveSession, string>({
query: (sessionId) => `sessions/${sessionId}`,
providesTags: ['ServerData'],
}),
}),
});
export const { useGetServerDataQuery, useGetActiveSessionQuery } = serverApi;
Usage in components:
function ServerComponent() {
const { data: serverData, isLoading, error } = useGetServerDataQuery();
if (isLoading) return <Spinner />;
if (error) return <ErrorMessage />;
return <ServerDisplay data={serverData} />;
}
Benefits:
- Automatic caching and cache invalidation
- Built-in loading/error states
- Automatic re-fetching
- Optimistic updates
- Request deduplication
- Background sync
3. Enhanced Type Safety
Current types:
interface LoadServerDataSuccessAction {
type: typeof types.LOAD_SERVER_DATA_SUCCESS;
payload: any; // ❌ Too generic
}
Improved types:
interface ServerData {
hostname: string;
sessionsCount: number;
isChainMember: boolean;
domain: {
name: string;
};
// ... specific fields instead of 'any'
}
interface ActiveSession {
sessionId: string;
isActive: boolean;
forwards: Forward[];
// ... specific structure
}
4. Selectors with Reselect
Current approach:
// Direct state access in components
const serverData = useSelector(state => state.server.data);
Memoized selectors:
import { createSelector } from '@reduxjs/toolkit';
// Base selectors
export const selectServerState = (state: RootState) => state.server;
export const selectServerData = (state: RootState) => state.server.data;
// Memoized computed selectors
export const selectIsServerLoading = createSelector(
selectServerData,
(serverData) => serverData.loading
);
export const selectServerSummary = createSelector(
selectServerData,
(serverData) => ({
hostname: serverData.hostname,
status: serverData.isChainMember ? 'Active' : 'Inactive',
sessions: serverData.sessionsCount
})
);
Migration Strategy
Phase 1: Setup RTK Query Infrastructure
- Install RTK Query dependencies
- Configure store with RTK Query middleware
- Create base API slice
Phase 2: Migrate One Feature (Server Module)
- Convert server module to RTK Query
- Update components to use RTK Query hooks
- Remove old Redux actions/reducers
- Test thoroughly
Phase 3: Gradual Migration
- Migrate one feature at a time
- Sessions → Forwards → System → Charts
- Keep both patterns during transition
Phase 4: Cleanup
- Remove old HTTP action utilities
- Consolidate remaining slices
- Update all TypeScript types
Benefits of Upgrade
Developer Experience
- 90% less boilerplate for API calls
- Automatic TypeScript inference
- Better debugging tools
- Standardized patterns
Performance
- Automatic request deduplication
- Smart caching strategies
- Background updates
- Optimistic updates
Maintenance
- Single source of truth for API logic
- Automatic error handling
- Built-in retry logic
- Cache invalidation strategies
Implementation Priority
- High Impact, Low Risk: RTK Query for new API endpoints
- Medium Impact: Convert existing simple GET endpoints
- High Impact, Higher Risk: Complex state management with mutations
- Polish: Enhanced selectors and type safety
Timeline Estimate
- Phase 1 (Setup): 1-2 days
- Phase 2 (First module): 2-3 days
- Phase 3 (Gradual migration): 1-2 weeks
- Phase 4 (Cleanup): 2-3 days
Total: 3-4 weeks for complete migration
Files to Reference
Current key files in the Redux architecture:
src/redux/configureStore.ts
- Store configurationsrc/redux/reducers/index.ts
- Root reducersrc/features/*/actionTypes.ts
- Action constantssrc/features/*/actionCreators.ts
- Thunk actionssrc/features/*/reducer.ts
- State managementsrc/features/*/api.ts
- API calls
These will be consolidated into:
src/store/store.ts
- RTK configured storesrc/api/
- RTK Query API slicessrc/features/*/slice.ts
- RTK slices for local state
Notes for Future Implementation
- Start with the server module as it has the simplest data flow
- Keep backward compatibility during transition
- Use TypeScript strict mode to catch type issues early
- Consider using RTK Query code generation for OpenAPI specs if available
- Plan for cache persistence if needed for offline functionality
Decision Points
- Do we need offline support? → Affects caching strategy
- Are there real-time updates needed? → Consider WebSocket integration
- How complex are the mutations? → Affects optimistic update strategy
- Do we need request cancellation? → RTK Query provides this automatically
This upgrade will significantly modernize the Redux architecture while maintaining all current functionality.