HMR Loading with Nuxt Page Refs

Im currently trying to implement a reactive expose system for an existing application. Some nuxt pages can expose a title and description which a grandparent component can access. It takes the data to make it reactive, but im not sure if I've implemented it correctly. Basically my BaseTabContainer handles a tab list (like your browser tabs) and also renders a BaseTabComponent that wraps a NuxtPage. We're exposing a title and description from the NuxtPage -> BaseTabComponent and then we're exposing the nuxtPageRef to the BaseTabContainer. My system works except when an HMR load occurs, since HMR loads reset refs (at least thats what im guessing). TL;DR -> HMR loads reset the nuxtPageRef and messes up my code. This isnt a bug in production since HMR stuff is for developers, but it becomes quite annoying.
2 Replies
kapa.ai
kapa.ai4d ago
Hi @quadralift. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- Your question is about implementing a reactive expose system with Nuxt Page Refs and the issues you're encountering with Hot Module Replacement (HMR). This is indeed a Nuxt-specific question, so I'll do my best to address it based on the available information. The issue you're experiencing with HMR resetting refs is a known behavior in Vue and Nuxt development environments. When HMR occurs, it can indeed reset component state, including refs. This is why you're seeing the nuxtPageRef being reset during development. To address this issue, we can consider a few approaches: 1. Use defineExpose and ref in your Nuxt pages: As mentioned in the Nuxt documentation (https://nuxt.com/docs/api/components/nuxt-page#pages-ref), you can use defineExpose to expose methods or properties from your Nuxt pages. Here's an example:
<script setup lang="ts">
const title = ref('Page Title')
const description = ref('Page Description')

defineExpose({
title,
description
})
</script>
<script setup lang="ts">
const title = ref('Page Title')
const description = ref('Page Description')

defineExpose({
title,
description
})
</script>
2. Access the exposed properties in the parent component: In your BaseTabComponent, you can access these exposed properties using the ref to the NuxtPage component:
<script setup lang="ts">
const pageRef = ref()

// You can access the exposed properties like this:
const pageTitle = computed(() => pageRef.value?.title)
const pageDescription = computed(() => pageRef.value?.description)

// Expose the page ref to the grandparent component
defineExpose({
pageRef
})
</script>

<template>
<NuxtPage ref="pageRef" />
</template>
<script setup lang="ts">
const pageRef = ref()

// You can access the exposed properties like this:
const pageTitle = computed(() => pageRef.value?.title)
const pageDescription = computed(() => pageRef.value?.description)

// Expose the page ref to the grandparent component
defineExpose({
pageRef
})
</script>

<template>
<NuxtPage ref="pageRef" />
</template>
3. Handle HMR updates: To address the HMR issue, you can listen for the content:update event in a client-side plugin. This event is fired when content is updated during development. Here's an example based on the Nuxt Content documentation (https://content.nuxt.com/v1/getting-started/advanced/#handling-hot-reload):
// plugins/hmr-update.client.js
export default function ({ app }) {
if (process.dev) {
window.onNuxtReady(($nuxt) => {
$nuxt.$on('content:update', ({ event, path }) => {
// Refresh the necessary data or components here
// For example, you could call a method to refresh your tab data
app.refreshTabs()
})
})
}
}
// plugins/hmr-update.client.js
export default function ({ app }) {
if (process.dev) {
window.onNuxtReady(($nuxt) => {
$nuxt.$on('content:update', ({ event, path }) => {
// Refresh the necessary data or components here
// For example, you could call a method to refresh your tab data
app.refreshTabs()
})
})
}
}
Remember to add this plugin to your nuxt.config.js:
export default {
plugins: [
'~/plugins/hmr-update.client.js'
]
}
export default {
plugins: [
'~/plugins/hmr-update.client.js'
]
}
4. Consider using useAsyncData or useFetch: For more robust data handling, especially with server-side rendering and HMR, consider using useAsyncData or useFetch to fetch and manage your page data. These composables are designed to work well with Nuxt's SSR capabilities and HMR. You can find more information in the Nuxt documentation on useAsyncData (https://nuxt.com/docs/api/composables/use-nuxt-data#optimistic-updates). While these approaches may not completely solve the HMR reset issue, they should provide a more robust way to handle your data and component structure, making it more resilient to HMR updates during development. Remember, as you noted, this is primarily a development-time issue and won't affect your production build. However, implementing these strategies should make your development experience smoother. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai4d ago
<@168796481992654848> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
Want results from more Discord servers?
Add your server