feat: Integrate Redux Provider and simplify Redux store configuration
Added Redux Provider to app layout and simplified Redux store to work properly with Next.js SSR. **Changes:** - Added ReduxProvider wrapper to root layout (app/layout.tsx) - Fixed ReduxProvider TypeScript type (React.ReactNode) - Simplified store configuration by removing @redux-offline package - Removed packages incompatible with SSR: - @redux-offline/redux-offline - redux-persist - localforage - Re-added NetworkStatusIndicator to main page (now works with Redux) - Kept custom offline middleware and sync middleware for offline-first functionality **Why:** The @redux-offline package and localforage try to access browser APIs (IndexedDB, localStorage) during SSR, causing "No available storage method found" errors. Our custom offline middleware provides the same functionality without SSR issues. **Result:** Redux store now works correctly with: - Network status detection - Offline action queuing - Custom sync middleware - Activities and children slices with optimistic updates Next step: Can add redux-persist back with proper SSR guards if needed. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,4 @@
|
||||
import { configureStore, Middleware } from '@reduxjs/toolkit';
|
||||
import { offline } from '@redux-offline/redux-offline';
|
||||
import offlineConfig from '@redux-offline/redux-offline/lib/defaults';
|
||||
import localforage from 'localforage';
|
||||
|
||||
// Slices
|
||||
import offlineReducer from './slices/offlineSlice';
|
||||
@@ -13,59 +10,6 @@ import networkReducer from './slices/networkSlice';
|
||||
import { offlineMiddleware } from './middleware/offlineMiddleware';
|
||||
import { syncMiddleware } from './middleware/syncMiddleware';
|
||||
|
||||
// Configure localforage for IndexedDB storage
|
||||
localforage.config({
|
||||
name: 'maternal-app',
|
||||
storeName: 'offline_data',
|
||||
driver: [localforage.INDEXEDDB, localforage.LOCALSTORAGE],
|
||||
});
|
||||
|
||||
// Custom offline configuration
|
||||
const customOfflineConfig = {
|
||||
...offlineConfig,
|
||||
persistOptions: {
|
||||
blacklist: ['_persist'], // Don't persist the persist state
|
||||
},
|
||||
// Effect function - how to execute side effects
|
||||
effect: async (effect: any, action: any) => {
|
||||
const { url, method = 'GET', body, headers = {} } = effect;
|
||||
|
||||
try {
|
||||
const response = await fetch(url, {
|
||||
method,
|
||||
body: body ? JSON.stringify(body) : undefined,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
...headers,
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
||||
}
|
||||
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
// Discard function - when to discard failed actions
|
||||
discard: (error: any, action: any, retries: number) => {
|
||||
// Discard after 5 retries or if it's a 4xx error
|
||||
const is4xxError = error.message?.includes('HTTP 4');
|
||||
return retries >= 5 || is4xxError;
|
||||
},
|
||||
// Retry function - calculate retry delay with exponential backoff
|
||||
retry: (action: any, retries: number) => {
|
||||
// Exponential backoff: 1s, 2s, 4s, 8s, 16s
|
||||
return Math.min(1000 * Math.pow(2, retries), 16000);
|
||||
},
|
||||
persistCallback: () => {
|
||||
console.log('[Redux Offline] State persisted to storage');
|
||||
},
|
||||
persistAutoRehydrate: true,
|
||||
};
|
||||
|
||||
export const store = configureStore({
|
||||
reducer: {
|
||||
offline: offlineReducer,
|
||||
@@ -83,17 +27,7 @@ export const store = configureStore({
|
||||
// Ignore these paths in the state
|
||||
ignoredPaths: ['items.dates'],
|
||||
},
|
||||
}).concat(
|
||||
offlineMiddleware as Middleware,
|
||||
syncMiddleware as Middleware,
|
||||
// Add redux-offline middleware
|
||||
offline(customOfflineConfig).middleware as Middleware
|
||||
),
|
||||
enhancers: (getDefaultEnhancers) =>
|
||||
getDefaultEnhancers().concat(
|
||||
// Add redux-offline enhancer
|
||||
offline(customOfflineConfig).enhancer
|
||||
),
|
||||
}).concat(offlineMiddleware, syncMiddleware),
|
||||
});
|
||||
|
||||
// Infer the `RootState` and `AppDispatch` types from the store itself
|
||||
|
||||
Reference in New Issue
Block a user