Bird
Raised Fist0
Vueframework~20 mins

Why composables matter in Vue - Challenge Your Understanding

Choose your learning style10 modes available
Challenge - 5 Problems
🎖️
Composable Mastery
Get all challenges correct to earn this badge!
Test your skills under time pressure!
🧠 Conceptual
intermediate
2:00remaining
Why use composables in Vue 3?

What is the main benefit of using composables in Vue 3's Composition API?

AThey automatically optimize rendering performance without extra code.
BThey allow reusing logic across components without duplicating code.
CThey replace templates with plain JavaScript functions for UI rendering.
DThey enforce strict typing on component props and events.
Attempts:
2 left
💡 Hint

Think about how you can share code between components easily.

❓ component_behavior
intermediate
2:00remaining
Effect of composable on component state

Given this composable and component code, what will be the value of count after clicking the button twice?

Vue
import { ref } from 'vue';

export function useCounter() {
  const count = ref(0);
  function increment() {
    count.value++;
  }
  return { count, increment };
}

// In component setup:
const { count, increment } = useCounter();

// Button click calls increment()
A2
B0
C1
Dundefined
Attempts:
2 left
💡 Hint

Each click calls increment() which increases count by 1.

❓ lifecycle
advanced
2:00remaining
Composables and component lifecycle hooks

Which lifecycle hook is best to use inside a composable to run code when the component using it is mounted?

Asetup
Bcreated
CbeforeDestroy
DonMounted
Attempts:
2 left
💡 Hint

Consider when the DOM is ready for interaction.

📝 Syntax
advanced
2:00remaining
Correct syntax for a composable function

Which option shows the correct syntax for a Vue 3 composable that provides a reactive message and a function to update it?

A
import { ref } from 'vue';
export function useMessage() {
  const message = ref('Hello');
  function updateMessage(newMsg) {
    message.value = newMsg;
  }
  return { message, updateMessage };
}
B
import { reactive } from 'vue';
export function useMessage() {
  const message = reactive('Hello');
  function updateMessage(newMsg) {
    message = newMsg;
  }
  return { message, updateMessage };
}
C
export function useMessage() {
  let message = 'Hello';
  function updateMessage(newMsg) {
    message = newMsg;
  }
  return { message, updateMessage };
}
D
import { ref } from 'vue';
export function useMessage() {
  const message = ref('Hello');
  function updateMessage(newMsg) {
    message = newMsg;
  }
  return { message, updateMessage };
}
Attempts:
2 left
💡 Hint

Remember how to update a ref value properly.

🔧 Debug
expert
3:00remaining
Why does this composable cause shared state bug?

Consider this composable used in multiple components. Why do all components share the same count value?

import { ref } from 'vue';
const count = ref(0);
export function useSharedCounter() {
  function increment() {
    count.value++;
  }
  return { count, increment };
}
ABecause <code>increment</code> does not update <code>count.value</code> correctly.
BBecause <code>ref</code> does not create reactive state inside composables.
CBecause <code>count</code> is declared outside the function, so it's shared across all uses.
DBecause the composable is missing a return statement.
Attempts:
2 left
💡 Hint

Think about where variables are declared and how that affects sharing.

Practice

(1/5)
1. Why are composables important in Vue applications?
easy
A. They compile Vue templates into JavaScript.
B. They automatically style components without CSS.
C. They replace the need for Vue Router.
D. They help reuse logic across multiple components easily.

Solution

  1. Step 1: Understand composables' purpose

    Composables are functions that let you reuse logic in Vue components.
  2. Step 2: Identify the correct benefit

    They help keep components clean by sharing logic, not styling or routing.
  3. Final Answer:

    They help reuse logic across multiple components easily. -> Option D
  4. Quick Check:

    Reusing logic = composables importance [OK]
Hint: Composables = reusable logic functions in Vue [OK]
Common Mistakes:
  • Thinking composables handle styling
  • Confusing composables with routing
  • Believing composables compile templates
2. Which of the following is the correct way to define a composable in Vue 3?
easy
A. function useCounter() { const count = ref(0); return { count }; }
B. const useCounter = new VueComponent() { count: 0 }
C. class useCounter { count = 0; }
D. const useCounter = () => { this.count = 0; }

Solution

  1. Step 1: Recall composable syntax

    Composables are functions that return reactive state or methods.
  2. Step 2: Check each option

    function useCounter() { const count = ref(0); return { count }; } defines a function returning a reactive ref, which is correct. Others misuse class, VueComponent, or this context.
  3. Final Answer:

    function useCounter() { const count = ref(0); return { count }; } -> Option A
  4. Quick Check:

    Composable = function returning reactive state [OK]
Hint: Composable must be a function returning reactive data [OK]
Common Mistakes:
  • Using class syntax for composables
  • Trying to use 'this' inside arrow functions
  • Confusing composables with components
3. Given this composable:
function useToggle() {
  const on = ref(false);
  function toggle() { on.value = !on.value; }
  return { on, toggle };
}

What will be the value of on.value after calling toggle() twice starting from initial state?
medium
A. undefined
B. true
C. false
D. null

Solution

  1. Step 1: Understand initial state

    The ref on starts as false.
  2. Step 2: Apply toggle twice

    First toggle flips false to true. Second toggle flips true back to false.
  3. Final Answer:

    false -> Option C
  4. Quick Check:

    Toggle twice returns to initial false [OK]
Hint: Toggle flips boolean; two flips return to start [OK]
Common Mistakes:
  • Assuming toggle only flips once
  • Confusing ref.value with ref itself
  • Expecting undefined or null values
4. What is wrong with this composable code?
function useData() {
  const data = ref(null);
  fetch('api/data').then(response => {
    data.value = response.json();
  });
  return { data };
}
medium
A. fetch returns a promise, so data.value is set to a promise, not actual data.
B. ref cannot hold null values initially.
C. The composable should not return data.
D. fetch cannot be used inside composables.

Solution

  1. Step 1: Analyze fetch usage

    fetch returns a promise; response.json() also returns a promise.
  2. Step 2: Identify mistake in assigning data.value

    Assigning data.value = response.json() sets it to a promise, not resolved data.
  3. Final Answer:

    fetch returns a promise, so data.value is set to a promise, not actual data. -> Option A
  4. Quick Check:

    response.json() returns promise, must await [OK]
Hint: Remember to await response.json() before assigning [OK]
Common Mistakes:
  • Not awaiting response.json()
  • Thinking ref can't start as null
  • Believing fetch is disallowed in composables
5. You want to share a composable that tracks window width and updates reactively on resize. Which approach correctly uses Vue composables to achieve this?
hard
A. function useWindowWidth() { const width = window.innerWidth; window.addEventListener('resize', () => { width.value = window.innerWidth; }); return { width }; }
B. function useWindowWidth() { const width = ref(window.innerWidth); onMounted(() => { window.addEventListener('resize', () => { width.value = window.innerWidth; }); }); onUnmounted(() => { window.removeEventListener('resize', () => { width.value = window.innerWidth; }); }); return { width }; }
C. function useWindowWidth() { const width = window.innerWidth; window.onresize = () => { width = window.innerWidth; }; return { width }; }
D. function useWindowWidth() { const width = ref(0); setInterval(() => { width.value = window.innerWidth; }, 1000); return { width }; }

Solution

  1. Step 1: Understand reactive state and lifecycle

    We need reactive width and proper event listener cleanup to avoid leaks.
  2. Step 2: Evaluate options for lifecycle management

    function useWindowWidth() { const width = ref(window.innerWidth); onMounted(() => { window.addEventListener('resize', () => { width.value = window.innerWidth; }); }); onUnmounted(() => { window.removeEventListener('resize', () => { width.value = window.innerWidth; }); }); return { width }; } uses onMounted and onUnmounted to add and remove listeners correctly, ensuring cleanup.
  3. Final Answer:

    function useWindowWidth() { const width = ref(window.innerWidth); onMounted(() => { window.addEventListener('resize', () => { width.value = window.innerWidth; }); }); onUnmounted(() => { window.removeEventListener('resize', () => { width.value = window.innerWidth; }); }); return { width }; } -> Option B
  4. Quick Check:

    Use lifecycle hooks to add/remove listeners [OK]
Hint: Add and remove listeners in lifecycle hooks for cleanup [OK]
Common Mistakes:
  • Not removing event listeners causing memory leaks
  • Using non-reactive variables for width
  • Using setInterval instead of event listeners
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard