skip to Main Content

I’m working on a Nuxt 3 project, and I have a question about the syntax in one of my files.

(I want to make it more SEO-friendly, so instead of using pages/posts/[id].vue, I’m using pages/posts/[id]/[title].vue.)

Here’s the code in the setup section of pages/posts/[id]/[title].vue:

type Post {
    title: string;
};

const route = useRoute();

const { data } = await useFetch(
    `/posts/${route.params.id}`
) as {
    data: Ref<Post>
};

definePageMeta({
    middleware: [
        (to: RouteLocationNormalized, from: RouteLocationNormalized) => {

            // I want to access the fetched data here
            if (to.params.title !== data.value.title) {
                navigateTo(`/posts/${data.value.id}/${data.value.title}`);
            }
        }
    ]
});

However, when I run the code, I receive a 500 error with the message "data is not defined." I know that I can fetch the post data in middleware independently, but it would result in duplicate requests, which is not ideal.

How can I improve my code to make it works and send the request only once?

Thanks a lot for anyone helps!

2

Answers


  1. Chosen as BEST ANSWER

    With @joelod's answer and the followings:

    Here is the solution:

    import { useNuxtApp, callWithNuxt } from '#app';
    
    // fetch the post data only once in middleware instead of the outside
    definePageMeta({
        middleware: [
            async (to: RouteLocationNormalized, from: RouteLocationNormalized) => {
    
                const nuxtApp = useNuxtApp();
    
                const { data: post } = await useFetch(
                    `/posts/${to.params.id}`
                ) as {
                    data: Ref<Post>
                };
    
                if (to.params.title !== post.value.title) {
                    await callWithNuxt(
                        nuxtApp,
                        () => {
                            navigateTo(`/posts/${post.value.id}/${post.value.title}`);
                        }
                    );
                }
                else {
                    await callWithNuxt(
                        nuxtApp,
                        () => {
                            nuxtApp.$requestData = post.value;
                        }
                    );
                }
            }
        ]
    });
    
    const nuxtApp = useNuxtApp();
    
    const post: Ref<Post> = ref(nuxtApp.$requestData as Post);
    
    // then you can use the `post` data anywhere
    useSeoMeta({
        title: `${post.value.title} | My Blog`,
    });
    

  2. You’ll need to store the data, I’m new to Nuxt and had the same question today and ended up figuring out a few minutes ago.

    In your middleware:

    const $store = useNuxtApp()
    $store.$requestData = data.value
    

    Then, in your page:

    <script setup>
    
        const $store = useNuxtApp()
        console.log('data', $store.$requestData)
        const data = $store.$requestData;
    
    </script>
    

    Of course I’m still very new to Nuxt (or JS frameworks in general), and any better solution would be welcome, in case I’m missing something here.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search