Il problema
Un centro notifiche con piΓΉ categorie (ferie, calendario, chat, promemoria) spesso ha dati che vivono
in database diversi con caratteristiche diverse: alcuni vanno letti una volta sola, altri devono
aggiornarsi in tempo reale. Usare lo stesso pattern per tutto spreca letture o introduce listener inutili.
The problem
A notification center with multiple categories (leave requests, calendar, chat, reminders) often has data
living in different databases with different characteristics: some need a one-time read, others need
real-time updates. Using the same pattern for everything wastes reads or introduces unnecessary listeners.
Firestore: lettura singola con filtri multipli
Per categorie dove lo storico non cambia spesso (es. richieste ferie), una query Firestore con
.get() β non .onSnapshot() β evita di tenere aperto un listener inutile.
Firestore: single read with multiple filters
For categories where history doesn't change often (e.g. leave requests), a Firestore query with
.get() β not .onSnapshot() β avoids keeping an unnecessary listener open.
const cutoff = Date.now() - 90 * 24 * 60 * 60 * 1000;
const tipi = [
'ferie_richiesta', 'ferie_approvata',
'ferie_rifiutata', 'ferie_annullata'
];
db.collection('activityLog')
.where('operatore', '==', currentUser)
.where('tipo', 'in', tipi)
.where('ts', '>=', cutoff)
.get() // una sola lettura, non real-time
.then(snap => snap.docs.map(d => ({ id: d.id, ...d.data() })));
RTDB: listener real-time su nodi giΓ esistenti
Calendario, promemoria e chat invece vivono sul Realtime Database β nodi piccoli, giΓ strutturati per
letture veloci. Agganciarsi con .on('value') su nodi esistenti non aggiunge costo significativo,
ed Γ¨ la scelta giusta quando i dati cambiano spesso e l'utente deve vederli aggiornarsi senza refresh.
RTDB: real-time listeners on existing nodes
Calendar, reminders and chat instead live on the Realtime Database β small nodes, already structured
for fast reads. Attaching with .on('value') to existing nodes doesn't add significant cost,
and it's the right choice when data changes often and the user needs to see updates without refreshing.
const ref = db.ref('calendario/' + reparto);
ref.on('value', snapshot => {
const eventi = snapshot.val() || {};
// Filtra: solo eventi giΓ scattati, creati dall'utente o del suo reparto
const visibili = Object.entries(eventi)
.filter(([id, ev]) =>
ev.firedAt && (ev.creatoDa === currentUser || ev.reparto === userReparto)
);
renderNotificheCalendario(visibili);
});
// Da chiamare allo smontaggio del componente / cambio utente
function cleanup() { ref.off('value'); }
Regola pratica: dati che cambiano raramente e vanno solo consultati β Firestore .get(). Dati che devono aggiornarsi live nell'interfaccia senza azione dell'utente β RTDB .on('value').
Rule of thumb: data that changes rarely and is just consulted β Firestore .get(). Data that must update live in the UI without user action β RTDB .on('value').
Attenzione al bootstrap: in una PWA con "ricordami", i listener real-time avviati al login manuale devono essere avviati anche nel percorso di restore sessione β altrimenti metΓ degli utenti lavora con notifiche silenziosamente disattivate dopo un refresh.
Watch the bootstrap: in a PWA with "remember me", real-time listeners started at manual login must also be started in the session-restore path β otherwise half your users end up with notifications silently disabled after a refresh.
Articolo correlato
Centro notifiche PWA: Firebase, Firestore e drawer a categorie β caso reale
Related article
PWA notification center: Firebase, Firestore and category drawer β real-world case
β