#How to use lazy components in composables?

6 messages · Page 1 of 1 (latest)

empty void
#

Hi! In new nuxt version they properly added delayed hydration, which is awesome, but I have composable like this (abstraction over nuxt ui component)

import { LazyPanelModalConfirmDelete } from '#components'

export function useConfirmModal(modalData: any) {
  const overlay = useOverlay()
  const isOpen = ref(false)

  const modal = overlay.create(LazyPanelModalConfirmDelete, { props: modalData })

  async function open() {
    isOpen.value = true
    await modal.open()
  }

  function close() {
    isOpen.value = true
    modal.close()
  }

  return { open, close }
}

Problem is that if modal is not opened I think component is hydrated, even if not the js for it is loaded, which is not desired behaviour. Any idea how I can do it? I found some examples with import() but I am not sure if it will help

rapid domeBOT
#

Hi @empty void. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

You're right that the lazy hydration features in Nuxt are powerful for performance optimization, but there are some nuances when using them with programmatic components via composables.

The Issue

In your current implementation, even though you're using LazyPanelModalConfirmDelete, the component is still being imported at the top of your file, which means its JavaScript will be loaded when the composable is used, regardless of whether the modal is opened.

Solution Approaches

1. Use Dynamic Import with defineLazyHydrationComponent

For Nuxt 3, you can use the new lazy hydration macros to explicitly control when components are loaded and hydrated:

export function useConfirmModal(modalData: any) {
  const overlay = useOverlay()
  const isOpen = ref(false)
  
  // Dynamically import the component only when needed
  const LazyModalComponent = defineLazyHydrationComponent(
    'visible', // or another strategy like 'idle'
    () => import('../components/PanelModalConfirmDelete.vue')
  )
  
  const modal = overlay.create(LazyModalComponent, { props: modalData })

  async function open() {
    isOpen.value = true
    await modal.open()
  }

  function close() {
    isOpen.value = false
    modal.close()
  }

  return { open, close }
}

This approach ensures the component is only loaded when needed and hydrated according to your chosen strategy.

2. Alternative: Create the Overlay Instance on Demand

Another approach is to create the overlay instance only when needed:

export function useConfirmModal(modalData: any) {
  const overlay = useOverlay()
  const isOpen = ref(false)
  let modal: ReturnType<typeof overlay.create> | null = null
#

async function open() {
// Create the modal only when opening it
if (!modal) {
const { LazyPanelModalConfirmDelete } = await import('#components')
modal = overlay.create(LazyPanelModalConfirmDelete, { props: modalData })
}

isOpen.value = true
await modal.open()

}

function close() {
if (modal) {
isOpen.value = false
modal.close()
}
}

return { open, close }
}


## Important Considerations

1. **Hydration Events**: If you need to listen for hydration events, all delayed hydration components emit a `@hydrated` event when they are hydrated [Listening to Hydration Events](<https://nuxt.com/docs/guide/directory-structure/components#listening-to-hydration-events>).

2. **Best Practices**: Remember that delayed hydration is best for non-critical, below-the-fold content. For modals that might need immediate interaction, consider if delaying hydration is appropriate [Caveats and Best Practices](<https://nuxt.com/docs/guide/directory-structure/components#caveats-and-best-practices>).

3. **Overlay Usage**: The `useOverlay` composable from Nuxt UI is designed to handle component creation and lifecycle, so make sure your implementation works with its expected behavior [useOverlay](<https://ui.nuxt.com/composables/use-overlay>).

By using one of these approaches, you can ensure that your modal component's JavaScript is only loaded when needed, improving the initial load performance of your application.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
#

@empty void Kapa.ai is still learning and improving, please let me know how I did by reacting below.

empty void