O filho LWC armazena em cache dados obsoletos por consulta do Apex @wired, Pai não pode atualizarApex () no filho por querySelector () porque o filho está escondido por if: true. O que fazer?
breve estrutura do aplicativo (veja a imagem): lista de componentes filhos de "item de linha" à direita (apenas um 1601xCC5Bulk nesta foto), contêiner com paletes à esquerda. << Allocate btn abre outro modal filho com um formulário (if: true ..). A lista de seleção deste formulário usa @wire apex para mostrar apenas paletes vazios, portanto, é atualizada pelo próprio controlador do formulário após DML.

problema surge ao alterar a quantidade de paletes por um pai, por exemplo, usando o botão vermelho à direita. este DML exclui o contêiner junto com os paletes.
Mas se o formulário oculto for aberto novamente, os valores de paletes antigos ainda estão presentes como valores da lista de opções, preciso atualizar esses dados. mas este filho está oculto, então inacessível por padrão: pai -> querySelector (child2) .method ()
- Desculpe pela pergunta newb: Existe uma maneira de acessar os métodos de componentes ocultos?
- Também estava pensando em mover a chamada para a consulta do Apex para o componente pai (fácil de acionar) e, em seguida, passá-la para o modal filho como um argumento de API, para que quando o modal aparecer, ele receberá dados atualizados. parece um pouco errado fazer, já que os pais levantam o fardo do filho. (talvez eu esteja errado)
- Eu também estava pensando em usar o recurso de chamada de retorno de criança para essa consulta de vértice, mas tem medo de loops de renderização infinitos?
- Desativar o cache do apex habilitado para aura seria uma coisa boa, mas parece impossível.
Aqui está a marcação básica, mostrando apenas todas as partes envolvidas
=== PAIS (com 2 filhos) ===
HTML
<template for:each={lineItems.data} for:item="lineItem">
<lightning-layout-item key={lineItem.Id} size="12">
<c-packing-list-line-item-card lineitem={lineItem} onallocatebuttonpress={openAllocationModal}></c-packing-list-line-item-card>
</lightning-layout-item>
</template>
<template if:true={isLineItemModalOpen}>
<c-packing-list-allocation-modal recordid={recordId} oncloseallocationmodal={closeAllocModal} onproductallocated={refreshData}></c-packing-list-allocation-modal>
</template>
JS
openAllocationModal(e) {
this.editItemId = e.detail;
this.isLineItemModalOpen = true;
}
closeAllocModal() {
this.isLineItemModalOpen = false;
}
=== CRIANÇA 1: cartão de item de linha de lista de embalagem === (aquele à direita, mostrando detalhes do produto, passa id para modal)
HTML
<lightning-button variant="brand" label="<< Allocate" data-itemid={lineitem.Id} onclick={openAllocationModal}></lightning-button>
JS
openAllocationModal(e) {
const selectEvent = new CustomEvent('allocatebuttonpress', { detail: e.target.dataset.itemid });
this.dispatchEvent(selectEvent);
}
=== CRIANÇA 2: Modal de alocação (exibição condicional) ===
HTML
<template if:true={showInsertButton}>
<button class="slds-button slds-button_brand" onclick={handleAllocationInsert}>Insert</button>
</template>
JS (provavelmente você está interessado apenas em closeModal () {}, outras coisas são para completude)
handleAllocationInsert() {
[...]
createRecord(recordInput)
.then((allocId) => {
this.showToast('success', 'Success', 'Product Allocated');
this.handleInsert(this.palletValue);
this.refreshPallets();
})
.catch((error) => {
this.showToast('error', 'Error creating record', error.body.message);
this.closeModal();
});
}
closeModal() {
// On save parent closes modal
console.log('closing 1');
const selectEvent = new CustomEvent('closeallocationmodal');
this.dispatchEvent(selectEvent);
this.spinner = false;
}
handleInsert(palletValue) {
// On save parent refreshes container view
const selectEvent = new CustomEvent('productallocated', {
detail: this.palletcontainers[palletValue].containerId
});
this.dispatchEvent(selectEvent);
this.closeModal();
}
Respostas
Desculpe pela pergunta newb: Existe uma maneira de acessar os métodos de componentes ocultos?
No. A criança é fisicamente removido do DOM e não existir de todo (excepto possivelmente numa cache componente).
Também estava pensando em mover a chamada para a consulta do Apex para o componente pai (fácil de acionar) e, em seguida, passá-la para o modal filho como um argumento de API, para que quando o modal aparecer, ele receberá dados atualizados. parece um pouco errado fazer, já que os pais levantam o fardo do filho. (talvez eu esteja errado)
Esta é, na verdade, uma maneira muito padrão de fazer isso. A criança só precisa se preocupar em mostrar os dados, que é o que foi projetada para fazer. Geralmente, é uma boa ideia obter / definir dados o mais alto possível na hierarquia de componentes (mas não mais alto do que o necessário).
Eu também estava pensando em usar o recurso de chamada de retorno de criança para essa consulta de vértice, mas tem medo de loops de renderização infinitos?
Má ideia, você terá loops infinitos, como você esperava. No entanto, usar o connectedCallback do componente pode fazer sentido aqui. Este evento só é chamado quando um componente é adicionado ou movido no DOM, então não teria problemas de loop infinito.
Desativar o cache do apex habilitado para aura seria uma coisa boa, mas parece impossível.
É perfeitamente possível, mas eu consideraria isso um último recurso. Na maioria das vezes, os dados não mudam até que o usuário faça algo, então o armazenamento em cache pode melhorar o desempenho. Dito isso, seu projeto também parece não precisar de chamadas frequentes, portanto, desabilitar o cache também é provavelmente aceitável.
Concluindo, eu diria que controlar os dados do pai seria a solução mais fácil. Essa também é a solução geralmente aceitável na maioria dos casos, já que os componentes filho normalmente só funcionam com os dados fornecidos pelo pai. Por exemplo, lightning-input
não faz nada com o servidor diretamente, mas comunica as mudanças ao pai por meio de eventos. É um design perfeitamente natural de usar.
Se você quiser que os filhos continuem fazendo o trabalho, tudo bem também, basta fazer uma chamada refreshApex em seu connectedCallback ou desabilitar o cache. Qualquer um dos dois deve resolver o seu problema, embora você possa querer testar em um grande conjunto de dados para ver qual das opções disponíveis oferece o melhor desempenho.