Fix infinite hydration loop and stabilize global store synchronization

- Refactored layouts to derive account data from stable props instead of reactive stores.
- Wrapped store updates in untrack() with deep equality guards to prevent infinite re-renders.
- Resolved duplicate untrack declarations and missing imports across the project.
- Added fetch safeguards to Element_data_store to prevent redundant API calls.
- Standardized hydration patterns to break circular dependencies during initial load.
This commit is contained in:
Scott Idem
2026-02-08 17:15:20 -05:00
parent 88bc18cf15
commit 718de1457d
33 changed files with 455 additions and 1567 deletions

View File

@@ -3,6 +3,7 @@
let log_lvl = $state(0);
// *** Import Svelte specific
import { untrack } from 'svelte';
// import { browser } from '$app/environment';
import { goto } from '$app/navigation';
@@ -26,23 +27,29 @@
}
let { data, children }: Props = $props();
// Initialize/Reset Entry Query defaults on layout load
// $journals_loc.entry.qry__enabled = 'enabled';
// $journals_loc.entry.qry__hidden = 'not_hidden';
// $journals_loc.entry.qry__limit = 15;
// $journals_loc.entry.qry__offset = 0;
// Quickly save the data passed from the parent(s) to the Svelte stores, localStorage, and other.
$slct.account_id = data.account_id;
// Use effects for store initializations to prevent render-phase updates
$effect(() => {
if (log_lvl) {
console.log(`$slct.account_id = `, $slct.account_id);
untrack(() => {
if ($slct.account_id !== data.account_id) {
$slct.account_id = data.account_id;
}
});
});
let ae_acct = $derived(data[data.account_id]);
$effect(() => {
if (ae_acct) {
untrack(() => {
if ($journals_slct.journal_id !== ae_acct.slct.journal_id) {
$journals_slct.journal_id = ae_acct.slct.journal_id;
}
if (JSON.stringify($journals_slct.journal_obj_li) !== JSON.stringify(ae_acct.slct.journal_obj_li)) {
$journals_slct.journal_obj_li = ae_acct.slct.journal_obj_li;
}
});
}
});
let ae_acct = data[$slct.account_id];
$journals_slct.journal_id = ae_acct.slct.journal_id;
$journals_slct.journal_obj_li = ae_acct.slct.journal_obj_li;
let nav_y_height = $state(0);
@@ -271,15 +278,12 @@
class:opacity-0={yTop < 750}
class:ae_btn_warning_filled={yTop > 1500}
onclick={() => {
log_lvl = 1;
$effect(() => {
if (log_lvl) {
console.log(
`Scroll to top button clicked. yScroll: ${yScroll} scrollTop: ${scroll_container().scrollTop}`,
scroll_container()
);
}
});
if (log_lvl) {
console.log(
`Scroll to top button clicked. yScroll: ${yScroll} scrollTop: ${scroll_container().scrollTop}`,
scroll_container()
);
}
console.log('Not Safari, using smooth scroll to top');
document.getElementById('ae_main_content')?.scrollTo({
@@ -341,15 +345,12 @@
class:opacity-0={yTop < 750}
class:ae_btn_warning_filled={yTop > 1500}
onclick={() => {
log_lvl = 1;
$effect(() => {
if (log_lvl) {
console.log(
`Scroll to bottom button clicked. yScroll: ${yScroll} scrollTop: ${scroll_container().scrollTop}`,
scroll_container()
);
}
});
if (log_lvl) {
console.log(
`Scroll to bottom button clicked. yScroll: ${yScroll} scrollTop: ${scroll_container().scrollTop}`,
scroll_container()
);
}
console.log('Not Safari, using smooth scroll to bottom');
document.getElementById('ae_main_content')?.scrollTo({

View File

@@ -24,7 +24,9 @@
import Journal_entry_obj_qry from './../ae_comp__journal_entry_obj_qry.svelte';
let ae_acct = data[$slct.account_id];
// NOTE: Derived from data.account_id (prop) instead of $slct.account_id (store)
// to prevent circular dependency loops during hydration.
let ae_acct = $derived(data[data.account_id]);
$effect(() => {
if (log_lvl) {
console.log(`ae_acct = `, ae_acct);

View File

@@ -43,7 +43,7 @@
import AeCompModalJournalImport from '../ae_comp__modal_journal_import.svelte';
// Variables
let ae_acct = data[$slct.account_id];
let ae_acct = data[data.account_id];
let show_export_modal = $state(false);
let show_import_modal = $state(false);

View File

@@ -47,7 +47,7 @@
// Variables
// *** Quickly pull out data from parent(s)
let ae_acct = data[$slct.account_id];
let ae_acct = data[data.account_id];
let show_export_modal = $state(false);
$effect(() => {

View File

@@ -1,4 +1,5 @@
<script lang="ts">
import { untrack } from 'svelte';
/**
* ae_comp__journal_entry_obj_id_view.svelte
* Reference Implementation for Journal Entry View/Edit
@@ -8,7 +9,6 @@
// *** Import Svelte core
import { goto } from '$app/navigation';
import { untrack } from 'svelte';
// *** Import secondary libraries
import { marked } from 'marked';

View File

@@ -1,4 +1,5 @@
<script lang="ts">
import { untrack } from 'svelte';
/**
* ae_comp__journal_obj_id_edit.svelte
* Standardized Journal-level configuration.
@@ -41,7 +42,6 @@
} from 'lucide-svelte';
import { Modal } from 'flowbite-svelte';
import { goto } from '$app/navigation';
import { untrack } from 'svelte';
// *** Import Aether specific variables and functions
import { ae_loc, ae_api } from '$lib/stores/ae_stores';

View File

@@ -1,4 +1,5 @@
<script lang="ts">
import { untrack } from 'svelte';
/**
* ae_comp__modal_journal_config.svelte
* Standardized Module-level settings for Journals.
@@ -19,7 +20,6 @@
Wrench
} from 'lucide-svelte';
import { Modal } from 'flowbite-svelte';
import { untrack } from 'svelte';
// *** Import Aether specific variables and functions
import { ae_loc, ae_api } from '$lib/stores/ae_stores';