Fix: Duration Is NaN in Vue.js Transitions

Error message:
{type} is NaN - the duration expression might be incorrect.
Components 2025-01-25

What Causes This Warning?

This warning occurs when a transition duration expression evaluates to NaN (Not a Number). This usually happens when parsing invalid strings or performing math operations on non-numeric values.

The Problem

<template>
  <!-- ❌ Duration evaluates to NaN -->
  <Transition :duration="parseInt('invalid')">
    <div v-if="show">Content</div>
  </Transition>

  <Transition :duration="undefined * 2">
    <div v-if="show">Content</div>
  </Transition>
</template>

The Fix

Validate Duration Values

<script setup>
import { computed } from 'vue'

const rawDuration = ref('500')

// ✅ Validate and provide fallback
const duration = computed(() => {
  const parsed = parseInt(rawDuration.value, 10)
  return isNaN(parsed) ? 300 : parsed
})
</script>

<template>
  <Transition :duration="duration">
    <div v-if="show">Content</div>
  </Transition>
</template>

Safe Number Conversion

// ✅ Helper function for safe conversion
function safeDuration(value, fallback = 300) {
  if (typeof value === 'number' && !isNaN(value)) {
    return value
  }

  const parsed = Number(value)
  return isNaN(parsed) ? fallback : parsed
}

// Usage
const duration = safeDuration(props.duration)

Common Scenarios

Dynamic Configuration

<script setup>
const config = ref({
  duration: null // Might be null/undefined
})

// ❌ Will be NaN
// :duration="config.duration * 1"

// ✅ Handle null/undefined
const duration = computed(() =>
  config.value.duration ?? 400
)
</script>

User Preferences

<script setup>
const userSpeed = ref('') // Empty string

// ✅ Validate user input
const duration = computed(() => {
  if (!userSpeed.value) return 400

  const speed = Number(userSpeed.value)
  if (isNaN(speed) || speed < 0) return 400
  if (speed > 5000) return 5000 // Cap at 5 seconds

  return speed
})
</script>

<template>
  <input v-model="userSpeed" type="number" min="0" max="5000" />
  <Transition :duration="duration">
    <div v-if="show">Content</div>
  </Transition>
</template>

Object Duration

<script setup>
const enterDuration = ref(null)
const leaveDuration = ref(undefined)

// ✅ Validate both enter and leave
const duration = computed(() => ({
  enter: Number(enterDuration.value) || 300,
  leave: Number(leaveDuration.value) || 200
}))
</script>

<template>
  <Transition :duration="duration">
    <div v-if="show">Content</div>
  </Transition>
</template>

Props Validation

<script setup>
const props = defineProps({
  duration: {
    type: Number,
    default: 400,
    validator: (value) => {
      // ✅ Validate during prop definition
      return !isNaN(value) && value >= 0
    }
  }
})
</script>

Multiplier Calculations

<script setup>
const baseSpeed = ref(1)
const baseDuration = 300

// ❌ Might produce NaN
// const duration = baseDuration * baseSpeed.value

// ✅ Validate before calculation
const duration = computed(() => {
  const speed = Number(baseSpeed.value)
  if (isNaN(speed) || speed <= 0) return baseDuration
  return Math.round(baseDuration / speed)
})
</script>

Quick Checklist

  • Always validate numeric inputs with isNaN()
  • Provide fallback values with ?? or ||
  • Use prop validators for duration props
  • Parse strings with Number() or parseInt()
  • Handle null/undefined cases explicitly
  • Cap durations to reasonable maximum values