Lo stato @tracked di un array o di un oggetto all’interno di un componente glimmer non attiva aggiornamenti quando si modifica un membro dell’array/oggetto.
Questo argomento parla di alcune opzioni per far sì che la tua vista si aggiorni correttamente. Volevo aggiungere un altro modo, poiché le opzioni discusse lì non hanno funzionato per me.
Come ho risolto questo problema: Invece di assegnare un elemento alla volta, assegna l’intero array in una volta sola. La stessa strategia funzionerebbe con un oggetto o qualsiasi altra struttura dati.
In un componente glimmer:
@tracked categories = [];
constructor() {
super(...arguments);
this.loadAllData();
}
async loadAllData() {
const categories = []
const waiting = this.siteSettings.county_fence_print_categories.split('|').map(async (cid, index) => {
const data = await this.loadData(`/c/${cid}/l/latest.json?period=monthly`)
return data.topic_list.topics
})
// QUESTA È LA RIGA DA NOTARE
// Poiché usiamo = direttamente sull'array, attiverà un aggiornamento.
// Mentre aggiungere all'array o impostare elementi per indice non attiverebbe un aggiornamento.
this.categories = await Promise.all(waiting)
}
async loadData(url) {
try {
const data = await ajax(url);
//console.log(`Got data for ${url}:`, data)
return data
} catch (error) {
console.error(`Failed to get data for ${url}:`, error);
}
}
Potresti farlo anche con un aggiornamento parziale. La cosa importante è che JavaScript rilevi che viene assegnato un valore diverso. Quindi, mentre .concat funzionerà, perché genera un nuovo array distinto dal vecchio:
this.categories = this.categories.concat(newValue)
Usare .push probabilmente non funzionerà, perché l’array risultante è lo stesso ID oggetto dell’originale, quindi JavaScript pensa che nulla sia cambiato.
this.categories.push(newValue)
this.categories = this.categories
Se stai lavorando con un oggetto, un modo semplice per generarne uno nuovo è con Object.assign() - che crea una nuova struttura dati estesa, come .concat sopra.
Questo è da tempo il caso anche per altri framework come Vue.js - puoi trovare argomenti su questo risalenti a 10 anni fa. Ha a che fare con il modo in cui viene implementato in JavaScript, probabilmente getter/setter sull’oggetto padre o l’API observe. Ma se è implementato con l’API observe, allora c’è un po’ meno scusa per questo comportamento, poiché sarebbe facile attivare il flag subtree… Forse scelgono di non farlo per motivi di prestazioni quando si osserva una struttura profondamente annidata? Ma divago, questi sono dettagli di implementazione delle librerie sottostanti. La soluzione alternativa sopra dovrebbe aiutarti a navigare in questo.