El niño de LWC almacena en caché los datos obsoletos mediante la consulta @wired Apex, el padre no puede actualizar elApex () en el niño por querySelector () porque el niño está oculto por if: true. ¿Qué hacer?
breve estructura de la aplicación (ver imagen): lista de componentes secundarios del "elemento de línea" a la derecha (solo un 1601xCC5Bulk en esta imagen), contenedor con paletas a la izquierda. << Allocate btn abre otro modal secundario con un formulario (si: verdadero ..) la lista de selección de este formulario usa @wire apex para mostrar solo paletas vacías, por lo que el controlador del formulario lo actualiza después de DML.

El problema surge cuando un padre cambia la cantidad de paletas, por ejemplo, usando el botón rojo a la derecha. este DML elimina el contenedor junto con las paletas.
Pero si el formulario oculto se abre de nuevo, los valores de paleta antiguos todavía están presentes como valores de lista de selección, necesito actualizar esos datos. pero este niño está oculto, por lo que es inalcanzable por estándar: parent -> querySelector (child2) .method ()
- Perdón por la nueva pregunta: ¿Hay alguna forma de acceder a los métodos del componente oculto?
- También estaba pensando en mover la llamada a la consulta de Apex hasta el componente principal (fácil de activar), luego pasarla al modal secundario como un argumento api, de modo que cuando aparezca modal, obtendrá datos actualizados. esto se siente un poco incorrecto, ya que los padres levantan la carga del niño (tal vez estoy equivocado)
- También estaba pensando en usar el servicio de devolución de llamada de un niño para esa consulta de vértice, pero ¿temo que los bucles de renderizado infinitos?
- Deshabilitar el almacenamiento en caché de auraEnabled apex sería algo agradable, pero parece imposible.
Aquí está el marcado básico, que muestra solo todas las partes involucradas
=== PADRE (con 2 hijos) ===
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;
}
=== NIÑO 1: embalaje-lista-línea-artículo-tarjeta === (el de la derecha, que muestra los detalles del producto, pasa la identificación al 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);
}
=== NIÑO 2: Modal de asignación (visualización condicional) ===
HTML
<template if:true={showInsertButton}>
<button class="slds-button slds-button_brand" onclick={handleAllocationInsert}>Insert</button>
</template>
JS (probablemente solo esté interesado en closeModal () {}, otras cosas son para completar)
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();
}
Respuestas
Perdón por la nueva pregunta: ¿Hay alguna forma de acceder a los métodos del componente oculto?
No. El niño se elimina físicamente del DOM y ya no existe en absoluto (excepto posiblemente en un caché de componentes).
También estaba pensando en mover la llamada a la consulta de Apex hasta el componente principal (fácil de activar), luego pasarla al modal secundario como un argumento api, de modo que cuando aparezca modal, obtendrá datos actualizados. esto se siente un poco incorrecto, ya que los padres levantan la carga del niño (tal vez estoy equivocado)
En realidad, esta es una forma muy estándar de hacer esto. El niño solo necesita preocuparse por mostrar datos, que es para lo que está diseñado. En general, es una buena idea obtener / establecer datos lo más alto posible en la jerarquía de componentes (pero no más alto de lo necesario).
También estaba pensando en usar el servicio de devolución de llamada de un niño para esa consulta de vértice, pero ¿temo que los bucles de renderizado infinitos?
Mala idea, obtendrás bucles infinitos, como esperas. Sin embargo, el uso de connectedCallback del componente podría tener sentido aquí. Este evento solo se llama cuando se agrega un componente o se mueve en el DOM, por lo que no tendría problemas de bucle infinito.
Deshabilitar el almacenamiento en caché de auraEnabled apex sería algo agradable, pero parece imposible.
Es perfectamente posible, pero lo consideraría un último recurso. La mayoría de las veces, los datos no cambian hasta que el usuario hace algo, por lo que el almacenamiento en caché puede mejorar el rendimiento. Dicho esto, su diseño también parece no necesitar llamadas frecuentes, por lo que deshabilitar el almacenamiento en caché probablemente también sea aceptable.
En conclusión, diría que controlar los datos del padre sería la solución más sencilla. Esta también es la solución generalmente aceptable en la mayoría de los casos, ya que los componentes secundarios normalmente solo funcionan con los datos que les proporciona el padre. Por ejemplo, lightning-input
no hace nada con el servidor directamente, pero comunica los cambios al padre a través de eventos. Es un diseño perfectamente natural de usar.
Si desea que los niños continúen haciendo el trabajo, también está bien, solo tenga una llamada refreshApex en su connectedCallback o deshabilite el almacenamiento en caché. Cualquiera de las dos debería resolver su problema, aunque es posible que desee realizar una prueba en un conjunto de datos grande para ver cuál de las opciones disponibles ofrece el mejor rendimiento.