Reputation: 127
I set up a composable for the currentYear under composables/getCurrentYear.ts
export const getCurrentYear = () => {
return new Date().getFullYear();
}
in my Footer component I defined it as
<script setup>
const currentYear = getCurrentYear()
</script>
and even though it was importing perfectly fine before, I am not getting:
500
getCurrentYear is not defined
at _sfc_main.setup (./components/AppFooter.js:56:23)
at callWithErrorHandling (./node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:171:22)
at setupStatefulComponent (./node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:7194:29)
at setupComponent (./node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:7149:11)
at renderComponentVNode (./node_modules/@vue/server-renderer/dist/server-renderer.cjs.js:628:17)
at Module.ssrRenderComponent (./node_modules/@vue/server-renderer/dist/server-renderer.cjs.js:94:12)
at _sfc_ssrRender (./components/AppLayout.js:26:31)
at renderComponentSubTree (./node_modules/@vue/server-renderer/dist/server-renderer.cjs.js:710:17)
at renderComponentVNode (./node_modules/@vue/server-renderer/dist/server-renderer.cjs.js:644:16)
My dependencies did not change, so I am slightly lost on why this all of the sudden stopped working:
"devDependencies": {
"@nuxtjs/i18n": "^8.0.0-beta.11",
"autoprefixer": "^10.4.13",
"nuxt": "^3.4.3",
"nuxt-simple-sitemap": "^2.4.23",
"postcss": "^8.4.23",
"tailwindcss": "^3.3.2"
},
"dependencies": {
"@csstools/css-parser-algorithms": "^2.1.1",
"@nuxtjs/google-fonts": "^3.0.0",
"contentful": "^10.1.8",
"contentful-rich-text-vue-renderer": "^3.1.0",
"gsap": "file:gsap-bonus.tgz",
"nuxt-swiper": "^1.1.0",
"typescript": "^5.0.4"
}
Upvotes: 4
Views: 8106
Reputation: 1
In nuxt 3 I created new function in composable to bridging the actions like in this project https://github.com/ilhammeidi/awrora-starter/blob/main/composables/uiTheme.js
// composable/ui.js
import { useState } from '#app';
const useThemeMode = () => (useState('mode', () => 'dark'));
const states = {
themeMode: useThemeMode,
};
// Execute state change
export function toggleDark(value) {
const themeMode = useThemeMode();
themeMode.value = value;
}
export default states;
<template>
<!-- components/UiSettings.vue -->
<div :class="themeMode">
<button @click="switchTheme('light')">change to light</button>
<button @click="switchTheme('dark')">change to dark</button>
</div>
</template>
<script setup>
import ui, { toggleDark } from '@/composables/ui';
const themeMode = ui.themeMode();
function switchTheme(val) {
toggleDark(val);
}
</script>
Upvotes: 0
Reputation: 5465
I had a similar issue but with Pinia and Just plain Vue3 where I returned an instance of an object directly, it worked at first for some reason but after a cold start it failed which led to this confusion, while it was valid code from a module perspective, it was not valid for the framework internals.
Nuxt will generate a declaration file for your composable under the hood which I think is acknowledged on next runtime, so then on next run it surfaces up as an error because you wrote it wrong but it couldn't tell you so on the first time around (some form of compilation race condition).
Concept of Pinia and composables in my view are similar in that there is a requirement for function wrapper (container) where from within you return methods an variables that are to be exposed from your container as if you where literally using different containers to store readily available resources like, one is full of nuts, another is full of bolts.
useBolts > getBolt(diameter: 4mm, length: 30mm)
useNuts > getNut(diameter: 4mm)
A nested composable would look like this:
fixings = useFixings > { bolts = useBolts(), nuts = useNuts() }
fixings.bolts.getBolt(diameter: 4mm, length: 30mm)
Your date code should look something like this in a container:
// composables/useDates.ts
export const useDates = () => { // The named container
// A container method
const getCurrentYear = () => new Date().getFullYear();
return { getCurrentYear } // Expose as public interface
}
Consuming your container:
// components/myComponenet.vue
<script setup>
const { getCurrentYear } = useDates();
console.log(getCurrentYear())
<script>
It is my understanding that this format is required so that functionality is returned as a set of key value pairs in order for Nuxt to generate key value type declarations in a useDate.d.ts
file that will appear in the .nuxt
folder within your project.
From the comments:
If a matching filename with <compsoable-name>.d.ts
is not generated inside the /.nuxt
directory or if this direcotry missing completely in the project after running it, then make sure your project files and folders are not set to readonly
ensure everything is writable
on your computer in the project.
This .nuxt
folder shold exist and be writable during development, it is generated when running dev
or if you run nuxi prepare
.
Here are some resources on .nuxt
directory:
https://nuxt.com/docs/guide/directory-structure/nuxt
Nuxt uses the .nuxt/ directory in development to generate your Vue application.
You should not touch any files inside since the whole directory will be re-created when running nuxt dev.
This directory is interesting if you want to learn more about the files Nuxt generates based on your directory structure.
https://nuxt.com/docs/guide/directory-structure/composables
Be aware that you have to run nuxi prepare, nuxi dev or nuxi build in order to let Nuxt generate the types. If you create a composable without having the dev server running, TypeScript will throw an error, such as Cannot find name 'useBar'.
Upvotes: 4
Reputation: 1380
From Nuxt3 official doc
Nuxt 3 uses the
composables/
directory to automatically import your Vue composables into your application using auto-imports!
So instead of naming composabled/getCurrentYear.ts
you can try composables/getCurrentYear.ts
Upvotes: 1