🪴 Rhitik's Notebook

Search

Search IconIcon to open search

Coding recommendations

Last updated Dec 11, 2023 Edit Source

# Use getters over computed where possible

In the context of Vue.js, which is a popular JavaScript framework for building user interfaces, there are two ways to create reactive properties or values: using getters and using computed properties. Let me explain both concepts and provide examples for better understanding. Getters:

Here’s an example of using a getter:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import { ref } from 'vue';

// Define a reactive property
const count = ref(0);

// Define a getter function
const doubleCount = () => count.value * 2;

// Usage
console.log(doubleCount()); // Access the value using the getter

In this example, doubleCount is a getter that calculates the double of the count reactive property. You can access its value by calling it like a function.

Computed Properties:

Here’s an example of using a computed property:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import { ref, computed } from 'vue';

// Define a reactive property
const count = ref(0);

// Define a computed property
const doubleCount = computed(() => count.value * 2);

// Usage
console.log(doubleCount.value); // Access the value like a property

In this example, doubleCount is a computed property that calculates the double of the count reactive property. You can access its value using the .value property.

The recommendation to use getters (() => value) over computed (computed(() => value)) typically comes from a performance perspective. Getters are often more efficient when you only need to calculate a value once based on other reactive properties, while computed properties are better suited for values that need to automatically update whenever their dependencies change.

So, if you have a simple calculation or transformation to perform on reactive data, it’s recommended to use a getter. If you need a value that automatically updates based on reactive dependencies, then you should use a computed property.

# Setting dynamic titles

nuxt.config does not allow the page title to be dynamic. Therefore, it is recommended to use titleTemplate in the app.vue file to add a dynamic title, which is then applied to all routes of your Nuxt app.

# Use your own cache keys

useAsyncData auto-generates generates a key for cache. But the autogenerated key only takes into account the file and line where useAsyncData is invoked, and so it is recommended to always create your own key to avoid unwanted behaviour, if you are creating your own custom composable that is wrapping useAsyncData. Data fetching · Get Started with Nuxt

Recommended ✅

1
2
3
4
5
const id = ref(1)

const { data, error } = await useAsyncData(`user:${id.value}`, () => {
  return myGetFunction('users', { id: id.value })
})

# When to use $fetch, useFetch, useAsyncData

The useFetch composable is meant to be invoked in setup method or called directly at the top level of a function in lifecycle hooks, otherwise you should use  $fetch method.

Minimize payload size

Recommendation ✅

The pick option helps you to minimize the payload size stored in your HTML document by only selecting the fields that you want returned from the composables.

1
2
3
4
5
6
7
8
9
<script setup lang="ts">
/* only pick the fields used in your template */
const { data: mountain } = await useFetch('/api/mountains/everest', { pick: ['title', 'description'] })
</script>

<template>
  <h1>{{ mountain.title }}</h1>
  <p>{{ mountain.description }}</p>
</template>

If you need more control or map over several objects, you can use the transform function to alter the result of the query.

1
2
3
4
5
const { data: mountains } = await useFetch('/api/mountains', { 
  transform: (mountains) => {
    return mountains.map(mountain => ({ title: mountain.title, description: mountain.description }))
  }
}

Refresh and execute

If you want to fetch or refresh data manually, use the execute or refresh function provided by the composables.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<script setup lang="ts">
const { data, error, execute, refresh } = await useFetch('/api/users')
</script>

<template>
  <div>
    <p>{{ data }}</p>
    <button @click="refresh">Refresh data</button>
  </div>
</template>

Recommendation ✅

The execute function is an alias for refresh that works in exactly the same way but is more semantic for cases when the fetch is  not immediate.

Defining components

Using <script setup lang="ts"> is the recommended way of declaring Vue components in Nuxt 3.

# Use of Ref

Avoid ❌ Never define const state = ref() outside of <script setup> or setup() function.
Such state will be shared across all users visiting your website and can lead to memory leaks!

Recommended ✅ Instead use const useX = () => useState('x')

Layout and Transition

<NuxtLayout /> renders incoming content via <slot />, which is then wrapped around Vue’s <Transition /> component to activate layout transition. For this to work as expected, it is recommended that <NuxtLayout /> is not the root element of the page component.

1
2
3
4
5
6
7
<template>
  <div>
    <NuxtLayout name="custom">
      <template #header> Some header template content. </template>
    </NuxtLayout>
  </div>
</template>

Recommendation ✅

1
2
3
<time :title="toTitleDate(date)" :datetime="date">
  {{ formatDate(date) }}
</time>

Functions called inside binding expressions will be called every time the component updates, so they should not have any side effects, such as changing data or triggering asynchronous operations.