Skip to content

Commit c013ccb

Browse files
Merge pull request #121 from CodeForPhilly/codex/fix-hydration-issues
Fix hydration mismatch in Explorer component
2 parents 8e34afe + b22969c commit c013ccb

File tree

2 files changed

+42
-17
lines changed

2 files changed

+42
-17
lines changed

src/components/Explorer.vue

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -845,7 +845,7 @@ export default {
845845
846846
this.initQuestionValues(questionDetails);
847847
848-
const twoUpIndex = Math.floor(Math.random() * twoUpImageCredits.length);
848+
const twoUpIndex = 0;
849849
return {
850850
results: [],
851851
total: 0,
@@ -1026,6 +1026,8 @@ export default {
10261026
},
10271027
// Browser only
10281028
async mounted() {
1029+
// Pick a random hero image after hydration to avoid SSR hydration mismatch
1030+
this.twoUpIndex = Math.floor(Math.random() * twoUpImageCredits.length);
10291031
this.displayLocation = localStorage.getItem("displayLocation")
10301032
this.zipCode= localStorage.getItem("zipCode")
10311033
this.filterValues["States"] = [localStorage.getItem("state")]

src/main.js

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,48 @@ import routerFactory from './router';
44
import storeFactory from './store';
55
import { createWebHistory } from "vue-router";
66

7-
// Browser-only logic for the store
7+
// Initialize with empty favorites for SSR consistency
8+
// This ensures the initial state matches what the server renders
9+
const initialFavorites = new Set();
10+
const store = storeFactory({ favorites: initialFavorites });
811

9-
const favorites = getFavoritesFromLocalStorage();
10-
11-
const store = storeFactory({ favorites });
12-
13-
store.subscribe((mutation, state) => {
14-
if (mutation.type === 'toggleFavorite') {
15-
localStorage.setItem('favorites', JSON.stringify([...state.favorites]));
16-
}
17-
});
12+
// Create the app and router
13+
const app = createSSRApp(App);
14+
const router = routerFactory({ history: createWebHistory() });
1815

19-
window.addEventListener('storage', () => {
20-
store.commit('setFavorites', getFavoritesFromLocalStorage());
21-
});
16+
// Mount the app first
17+
app.use(router).use(store).mount('#app');
2218

23-
const router = routerFactory({ history: createWebHistory() });
24-
createSSRApp(App).use(router).use(store).mount('#app');
19+
// After the app is mounted and hydration is complete, we can safely access localStorage
20+
// and update the state without causing hydration mismatches
21+
if (typeof window !== 'undefined') {
22+
// Use a small timeout to ensure hydration is complete
23+
setTimeout(() => {
24+
// Now it's safe to load favorites from localStorage
25+
const favorites = getFavoritesFromLocalStorage();
26+
if (favorites.size > 0) {
27+
store.commit('setFavorites', favorites);
28+
}
29+
30+
// Set up localStorage sync for future changes
31+
store.subscribe((mutation, state) => {
32+
if (mutation.type === 'toggleFavorite') {
33+
localStorage.setItem('favorites', JSON.stringify([...state.favorites]));
34+
}
35+
});
36+
37+
window.addEventListener('storage', () => {
38+
store.commit('setFavorites', getFavoritesFromLocalStorage());
39+
});
40+
}, 0);
41+
}
2542

2643
function getFavoritesFromLocalStorage() {
27-
return new Set(JSON.parse(localStorage.getItem('favorites') || '[]'));
44+
if (typeof localStorage === 'undefined') return new Set();
45+
try {
46+
return new Set(JSON.parse(localStorage.getItem('favorites') || '[]'));
47+
} catch (e) {
48+
console.error('Error parsing favorites from localStorage:', e);
49+
return new Set();
50+
}
2851
}

0 commit comments

Comments
 (0)