Weekly Vue News #113 - Use Your Composables Synchronously

Weekly Vue News #113

Use Your Composables Synchronously

Hi 👋

I changed the structure of the newsletter. I separated the content for Vue and Nuxt and moved the tip section after the Vue & Nuxt content sections. Additionally, I'm now limiting the number of links to 5 per section.

I hope you like it. Let me know what you think.

Have a lovely week ☀️


To support me:

Vue
📕 Building Reusable Components that are ACTUALLY Reusable with Vue.js
👉🏻 In this article, you'll explore the concept of reusable components, the problems faced when applying them, and why overcoming them as best as possible is essential.
medium.com
📕 My Top 5 Tips for using Pinia
👉🏻 The Top 5 Tips for using Pinia by Eduardo San Martin Morote, the author of Pinia himself.
masteringpinia.com
📕 Build an exceptional Infinite Scroller using Intersection Observer in Vue3
👉🏻 This article walks through the process of building a Vue 3 single-page component that wraps the Intersection Observer API and makes it easy to use in our Vue applications.
sandip-shrestha.medium.com
🛠️ Shadcn for Vue
👉🏻 A community-led Vue port of the React-oriented "shadcn/ui" component library.
👉🏻 A suite of attractive components built with Tailwind CSS and Radix UI that you can easily "copy and paste" into your apps.
www.shadcn-vue.com
🛠️ UI Lib Picker
👉🏻 Pick the right UI Library for your Vue 3 or Nuxt 3 Project.
ui-libs.vercel.app

Nuxt
📕 useFetch in Nuxt 3: The Proper Way
👉🏻 "useFetch is a composable and should be called in essentially the context of the setup method. It provides a way to trigger fetch calls."
alex.party

📅 Events
North America's premier Vue.js Conference
👉🏻 9-10 November 2023, Toronto, Canada.
www.vuetoronto.com

💬 Quote of the week

🔥 Vue Tip: Use Your Composables Synchronously

You should always call your composables synchronously in setup() hook or <script setup>. It would be best not to use await or Promise.all() when calling your composables. For example, the following code using the setup() hook is not recommended:

Component.vue
1<script>
2import { ref, watch, onMounted, onUnmounted } from 'vue'
3
4export default {
5 async setup() {
6 const counter = ref(0)
7
8 watch(counter, () => console.log(counter.value))
9
10 // ✅ this lifecycle hook is called
11 onMounted(() => console.log('Setup Hook: Mounted'))
12
13 // ⌛ an async operation is started
14 await new Promise((resolve) => {
15 setTimeout(() => {
16 console.log('Setup Hook: Resolve await')
17 resolve()
18 }, 1000)
19 })
20
21 // ☠️ this lifecycle hook is not called
22 onUnmounted(() => console.log('Setup Hook: Unmounted'))
23
24 // ⚠️ watcher works but is not automatically disposed
25 // after the component is destroyed, which can cause a memory leak
26 watch(counter, (newCounter) => {
27 console.log('Setup Hook: Watcher', newCounter)
28 })
29
30 return { counter }
31 },
32
33 mounted() {
34 console.log('Setup Hook: Mounted', this.count) // 0
35 },
36}
37</script>

Vue must know the currently active component instance to register lifecycle hooks, watchers, and computed properties. If you call your composables asynchronously, Vue will not be able to determine the current active component instance and cannot register these features.

<script setup> is the only place to call composables after using await. After the async operation, the compiler automatically restores the active instance context for you.

Component.vue
1<script setup>
2import { ref, watch, onMounted, onUnmounted } from 'vue'
3
4const counter = ref(0)
5
6watch(counter, () => console.log(counter.value))
7
8// ✅ this lifecycle hook is called
9onMounted(() => console.log('Script Setup: Mounted'))
10
11// the await statement
12await new Promise((resolve) => {
13 setTimeout(() => {
14 console.log('Script Setup: Resolve await')
15 resolve()
16 }, 1000)
17})
18
19// ✅ this lifecycle hook is called
20onUnmounted(() => console.log('Script Setup: Unmounted'))
21
22// ✅ watcher works and is automatically disposed after the component is destroyed
23watch(counter, (newCounter) => {
24 console.log('Script Setup: Watcher', newCounter)
25})
26</script>

Only in <script setup> you can call your composables after using await. After the async operation, the compiler automatically restores the active instance context for you.

Recommendation

I suggest you always call your composables synchronously in both setup() hook and <script setup>. Sometimes, you can call them in lifecycle hooks like onMounted(). This will ensure that your composables are always called in the correct context and that Vue can register all the necessary features.

A good example is the useFetch composable to fetch data from an API:

useFetch.ts
1import { ref } from 'vue'
2
3export const useFetch = (url: string) => {
4 const data = ref(null)
5 const error = ref(null)
6
7 fetch(url)
8 .then((res) => res.json())
9 .then((json) => (data.value = json))
10 .catch((err) => (error.value = err))
11
12 return { data, error }
13}

You can call this composable synchronously in the setup() hook or <script setup>:

Component.vue
1<script setup>
2import { useFetch } from './useFetch.ts'
3
4const { data, error } = useFetch('/api/data')
5</script>

Try it yourself in the following StackBlitz project:

Async with Composition API is an excellent article by Anthony Fu that explains this topic in more detail.

😂 Fun

🧑🏻‍💻 In Other News
📕 14 Linting Rules To Help You Write Asynchronous Code in JavaScript
👉🏻 This article presents 14 ESLint rules for asynchronous code, like setting a limit for nested callbacks, which prevents debugging headaches down the road.
maximorlov.com
📕 A systematic approach to debugging
👉🏻 This article presents a systematic approach to debugging that focuses on understanding first.
ntietz.com
🛠️ Chrono
👉🏻 A natural language date parser in JavaScript.
👉🏻 It is designed to handle most date/time formats and extract information from any given text.
github.com
🛠️ npm-check-updates
👉🏻 Find newer versions of package dependencies than what your package.json allows.
👉🏻 It upgrades your package.json dependencies to the latest versions, ignoring specified versions.
github.com

Comments? Join the discussion about this issue here.

Until next week,

Unsubscribe from this newsletter
Holzapfelkreuther Str. 19, 81375 Munich, Germany

评论

此博客中的热门博文

Scripting News: Tuesday, June 11, 2024

Scripting News: Tuesday, February 13, 2024