O estado @tracked de um array ou objeto dentro de um componente glimmer não aciona atualizações quando você altera um membro do array/objeto.
Este tópico fala sobre algumas opções para fazer sua visualização atualizar corretamente. Eu queria adicionar outra maneira, pois as opções discutidas lá não funcionaram para mim.
Como resolvi isso: Em vez de atribuir um elemento por vez, atribua o array inteiro de uma vez. Essa mesma estratégia funcionaria com um objeto ou qualquer outra estrutura de dados.
Em um 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
})
// ESTA É A LINHA PARA NOTAR
// Como usamos = diretamente no array, isso acionará uma atualização.
// Enquanto adicionar ao array ou definir elementos por índice não acionaria uma atualização.
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);
}
}
Você também poderia fazer isso com uma atualização parcial. O importante é que o Javascript detecte que um valor diferente está sendo atribuído. Portanto, embora .concat funcione, porque ele gera um novo array distinto do antigo:
this.categories = this.categories.concat(newValue)
Usar .push provavelmente não funcionará, porque o array resultante é o mesmo ID de objeto do original, portanto, o Javascript pensa que nada mudou.
this.categories.push(newValue)
this.categories = this.categories
Se você estiver trabalhando com um objeto, uma maneira fácil de gerar um novo é com Object.assign() - que cria uma nova estrutura de dados estendida, como .concat acima.
Isso tem sido o caso há muito tempo para outros frameworks como Vue.js também - você pode encontrar tópicos sobre isso datando de 10 anos atrás. Tem a ver com a forma como está sendo implementado em Javascript, provavelmente getters/setters no objeto pai ou a API observe. Mas se for implementado com a API observe, então há um pouco menos de desculpa para esse comportamento, já que seria fácil alternar o sinalizador subtree… Talvez eles escolham não fazer isso por preocupações de desempenho ao observar uma estrutura profundamente aninhada? Mas divago, esses são detalhes de implementação das bibliotecas subjacentes. A solução alternativa acima deve ajudá-lo a navegar por isso.