Vue stuff

4 min read
~610 words
NO DATE
DRAFT

Maintaining reactivity

You should only access the value of a ref, computed, a prop, or a key in a reactive in your <template>, or inside a function.

Only top-level refs are unwrapped in your <template>

computeds are lazy

computeds are lazy in 2 ways:

  1. The getter function will only be run if the computed's value is accessed.
  2. The getter function will only automatically re-run if the computed is used in a reactive scope, for example in your <template>, inside another computed, or as a watch target.

You can't use double quotes inside dynamic props

Vue requires double quotes (") around your dynamic props, so you can't use them in the value of your prop. Instead you can only use single quotes (') and backticks (`) in your template. If you really need to use double quotes you need to make a variable in your <script> section.

For example, these work:

vue
<script setup lang="ts">
const stringWithDoubleQuotes = '"'
</script>
 
<template>
  <input :value="'hello'" />
  <input :value="`hello`" />
  <input :value="stringWithDoubleQuotes" />
</template>

But the following don't, even though the syntax highlighting looks okay. See also in the Vue SFC Playground

vue
<template>
  <input :value="'"'" />
  <input :value="`"`" />
  <input :value="'\"'" />
</template>

Changing routes in vue-router and nuxt

If you switch routes using the route's name (vs using the actual path), you only need to provide params that have changed!! For example, if you're on the /agents/agent-1/tasks/task-1 route and you want to navigate to the /agents/agent-1/tasks/task-2 route, you can do this

vue
<template>
  <Link
    :to="{
      name: 'agent-agentId-tasks-taskId',
      params: {
        taskId: 'task-2',
      },
    }"
  >
    To next task
  </Link>
</template>

or

typescriptjavascript
const router = useRouter()
 
router.push({
  name: 'agent-agentId-tasks-taskId',
  params: {
    taskId: 'task-2',
  },
})
const router = useRouter()
 
router.push({
  name: 'agent-agentId-tasks-taskId',
  params: {
    taskId: 'task-2',
  },
})

Warning

This only works for route params, but NOT query. The query is overwritten every time you navigate to a new page.

Probably don't use proxyRefs

What is proxyRefs?

proxyRefs is a nice utility that unwraps ref keys on an object (can't find the docs for this 😕). For example, the following 2 snippets have the same effect on the message ref.

Without proxyRefs
typescriptjavascript
const message = ref('hi')
 
console.log(message.value) // 'hi'
 
message.value = 'hello'
const message = ref('hi')
 
console.log(message.value) // 'hi'
 
message.value = 'hello'
With proxyRefs
typescriptjavascript
const message = ref('hi')
 
const proxyObject = proxyRefs({
  message,
})
 
console.log(proxyObject.message) // 'hi'
 
proxyObject.message = 'hello' // updates the underlying `message` ref
const message = ref('hi')
 
const proxyObject = proxyRefs({
  message,
})
 
console.log(proxyObject.message) // 'hi'
 
proxyObject.message = 'hello' // updates the underlying `message` ref

Sidenote: I can't find any reference to this in the docs, so maybe we're not supposed to use it at all

Using proxyRefs can make it harder to reason about when you're accessing a "reactive" value. This is an especially big issue with custom composables / hooks if you wrap the whole return value in proxyRefs and destructure its return value:

typescriptjavascript
export const useStuff = () => {
  const message = ref('hi')
 
  return proxyRefs({ message })
}
 
// in another file...
 
/**
 * Here, `message` will just be a string, and not a ref, so anywhere you use
 * `message` won't receive updates!!!
 */
const { message } = useStuff()
export const useStuff = () => {
  const message = ref('hi')
 
  return proxyRefs({ message })
}
 
// in another file...
 
/**
 * Here, `message` will just be a string, and not a ref, so anywhere you use
 * `message` won't receive updates!!!
 */
const { message } = useStuff()

The exception

For me, the main exception to this is if you're using TanStack Query, since it returns an object where each value at the top level is a ref. I don't like destructuring the return value of a useQuery or useMutation (even in React), and I find it more ergonomic to write query.data instead of query.data.value. When I use proxyRefs for this, I generally try to use it directly at the useQuery call:

typescriptjavascript
const stuff = proxyRefs(
  useQuery({
    queryKey: ['key', 'for', 'stuff'],
    queryFn: () => getStuff(),
  })
)
const stuff = proxyRefs(
  useQuery({
    queryKey: ['key', 'for', 'stuff'],
    queryFn: () => getStuff(),
  })
)
Found a mistake, or want to suggest an improvement? Source on GitHub here
and see edit history here