| 68 | * statement reuse {@link seedSheetStatement} directly instead. |
| 69 | */ |
| 70 | export const useSheetStatement = ({ |
| 71 | enabled, |
| 72 | sheetName, |
| 73 | getLocalSheet, |
| 74 | }: { |
| 75 | enabled: boolean; |
| 76 | sheetName: string; |
| 77 | getLocalSheet?: (name: string) => Sheet | undefined; |
| 78 | }): SheetStatementSnapshot => { |
| 79 | const [snapshot, setSnapshot] = useState<SheetStatementSnapshot>(() => |
| 80 | enabled ? seedSheetStatement(sheetName, getLocalSheet) : EMPTY_SNAPSHOT |
| 81 | ); |
| 82 | |
| 83 | const seedKey = enabled ? sheetName : ""; |
| 84 | const [trackedSeedKey, setTrackedSeedKey] = useState(seedKey); |
| 85 | if (seedKey !== trackedSeedKey) { |
| 86 | setTrackedSeedKey(seedKey); |
| 87 | setSnapshot( |
| 88 | enabled ? seedSheetStatement(sheetName, getLocalSheet) : EMPTY_SNAPSHOT |
| 89 | ); |
| 90 | } |
| 91 | |
| 92 | useEffect(() => { |
| 93 | if (!enabled || !sheetName) { |
| 94 | return; |
| 95 | } |
| 96 | // Local and already-cached sheets were seeded synchronously above. |
| 97 | if (extractSheetUID(sheetName).startsWith("-")) { |
| 98 | return; |
| 99 | } |
| 100 | if (useAppStore.getState().getSheetByName(sheetName)) { |
| 101 | return; |
| 102 | } |
| 103 | |
| 104 | let canceled = false; |
| 105 | const load = async () => { |
| 106 | try { |
| 107 | const sheet = await useAppStore |
| 108 | .getState() |
| 109 | .getOrFetchSheetByName(sheetName); |
| 110 | if (canceled || !sheet) { |
| 111 | return; |
| 112 | } |
| 113 | setSnapshot(snapshotOfSheet(sheet)); |
| 114 | } finally { |
| 115 | if (!canceled) { |
| 116 | setSnapshot((prev) => |
| 117 | prev.isLoading ? { ...prev, isLoading: false } : prev |
| 118 | ); |
| 119 | } |
| 120 | } |
| 121 | }; |
| 122 | void load(); |
| 123 | return () => { |
| 124 | canceled = true; |
| 125 | }; |
| 126 | // getLocalSheet is intentionally excluded: only the synchronous seed reads |
| 127 | // it, and the effect handles remote sheets exclusively. |