Bird
Raised Fist0
Vueframework~20 mins

Creating a custom composable in Vue - Practice Exercises

Choose your learning style10 modes available
Challenge - 5 Problems
🎖️
Vue Composable Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
❓ component_behavior
intermediate
2:00remaining
What does this custom composable return?
Consider this Vue 3 custom composable that tracks window width. What is the output when you call useWindowWidth()?
Vue
import { ref, onMounted, onUnmounted } from 'vue';

export function useWindowWidth() {
  const width = ref(window.innerWidth);

  function updateWidth() {
    width.value = window.innerWidth;
  }

  onMounted(() => {
    window.addEventListener('resize', updateWidth);
  });

  onUnmounted(() => {
    window.removeEventListener('resize', updateWidth);
  });

  return { width };
}
AA function that returns the current window width when called
BA number representing the window width at the time of calling
CAn object with a reactive property 'width' that updates on window resize
DAn array containing the window width and a function to update it
Attempts:
2 left
💡 Hint
Think about what ref returns and how the event listeners affect it.
❓ state_output
intermediate
1:30remaining
What is the value of count.value after calling useCounter() and incrementing twice?
Given this custom composable for a counter, what is the value of count.value after calling increment() twice?
Vue
import { ref } from 'vue';

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

// Usage example:
const { count, increment } = useCounter();
increment();
increment();
A0
Bundefined
C1
D2
Attempts:
2 left
💡 Hint
Remember that count is a ref and increments by 1 each time increment() is called.
📝 Syntax
advanced
2:30remaining
Which option correctly defines a composable that returns a reactive boolean toggled by a function?
Select the option that correctly defines a Vue 3 composable returning a reactive boolean isActive and a function toggle to flip its value.
A
import { ref } from 'vue';
export function useToggle() {
  const isActive = ref(false);
  function toggle() {
    isActive.value = !isActive.value;
  }
  return { isActive, toggle };
}
B
import { ref } from 'vue';
export function useToggle() {
  let isActive = false;
  function toggle() {
    isActive = !isActive;
  }
  return { isActive, toggle };
}
C
import { reactive } from 'vue';
export function useToggle() {
  const state = reactive({ isActive: false });
  function toggle() {
    state.isActive = !state.isActive;
  }
  return { isActive: state.isActive, toggle };
}
D
import { ref } from 'vue';
export function useToggle() {
  const isActive = ref(false);
  function toggle() {
    isActive = !isActive;
  }
  return { isActive, toggle };
}
Attempts:
2 left
💡 Hint
Remember to use .value to access or update refs.
🔧 Debug
advanced
2:00remaining
Why does this composable not update the reactive property on button click?
This composable is intended to toggle a boolean on button click, but the UI does not update. What is the cause?
Vue
<template>
  <button @click="toggle">Toggle</button>
  <p>{{ isActive }}</p>
</template>

<script setup>
import { ref } from 'vue';

const isActive = ref(false);

function toggle() {
  isActive.value = !isActive.value;
}
</script>
AThe ref is not imported from 'vue'
BThe toggle function assigns a new value to the ref variable instead of updating its .value property
CThe button click event is not bound correctly
DThe template does not use double curly braces to display isActive
Attempts:
2 left
💡 Hint
Check how you update reactive refs inside functions.
🧠 Conceptual
expert
1:30remaining
What is the main advantage of using a custom composable in Vue 3?
Why do developers create custom composables in Vue 3? Choose the best explanation.
ATo reuse reactive logic across multiple components without repeating code
BTo replace Vue components with simpler functions
CTo automatically generate UI templates from JavaScript code
DTo avoid using the Composition API and stick to Options API
Attempts:
2 left
💡 Hint
Think about code reuse and organization in Vue 3.

Practice

(1/5)
1. What is the main purpose of creating a custom composable in Vue?
easy
A. To define global CSS styles
B. To reuse reactive logic across multiple components
C. To create new Vue directives
D. To register components globally

Solution

  1. Step 1: Understand what composables do

    Custom composables are functions that encapsulate reactive logic to be reused.
  2. Step 2: Identify the purpose in Vue components

    They help share logic without repeating code in multiple components.
  3. Final Answer:

    To reuse reactive logic across multiple components -> Option B
  4. Quick Check:

    Reusable reactive logic = B [OK]
Hint: Composables = reusable reactive logic functions [OK]
Common Mistakes:
  • Confusing composables with styling or directives
  • Thinking composables register components
  • Assuming composables handle templates
2. Which of the following is the correct way to start a custom composable function in Vue 3?
easy
A. function useData() { const count = ref(0); return { count }; }
B. const useData = () => { const count = reactive(0); return count; }
C. function useData() { const count = ref(0); }
D. const useData = () => { return ref({ count: 0 }); }

Solution

  1. Step 1: Check function declaration and return

    function useData() { const count = ref(0); return { count }; } declares a function named with 'use' prefix and returns reactive refs.
  2. Step 2: Validate reactive usage and return object

    function useData() { const count = ref(0); return { count }; } returns an object with the reactive ref, which is correct pattern.
  3. Final Answer:

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

    Composable returns reactive refs in object = D [OK]
Hint: Composable must return reactive data inside an object [OK]
Common Mistakes:
  • Not returning reactive data
  • Returning reactive primitive directly instead of object
  • Missing 'use' prefix in function name
3. Given this composable code, what will be logged when calling increment() twice?
import { ref } from 'vue';

export function useCounter() {
  const count = ref(0);
  function increment() {
    count.value++;
    console.log(count.value);
  }
  return { count, increment };
}
medium
A. Undefined and then 1
B. 0 and then 1
C. 2 and then 3
D. 1 and then 2

Solution

  1. Step 1: Understand initial count value

    The count starts at 0 as a ref.
  2. Step 2: Trace increment calls and console logs

    Each increment increases count.value by 1 and logs it immediately.
  3. Final Answer:

    1 and then 2 -> Option D
  4. Quick Check:

    Increment twice logs 1 then 2 [OK]
Hint: Ref value increments and logs immediately [OK]
Common Mistakes:
  • Confusing ref.value with ref itself
  • Assuming count starts at 1
  • Thinking console logs before increment
4. Identify the error in this composable code:
import { ref } from 'vue';

export function useToggle() {
  const state = ref(false);
  function toggle() {
    state = !state;
  }
  return { state, toggle };
}
medium
A. ref should be reactive instead
B. Missing return statement
C. Cannot reassign a const ref variable directly
D. toggle function should be async

Solution

  1. Step 1: Check how ref is updated

    The code tries to assign 'state = !state', which reassigns the const variable.
  2. Step 2: Correct way to update ref value

    Should update 'state.value = !state.value' instead of reassigning 'state'.
  3. Final Answer:

    Cannot reassign a const ref variable directly -> Option C
  4. Quick Check:

    Update ref.value, not ref variable [OK]
Hint: Update ref.value, never reassign ref variable [OK]
Common Mistakes:
  • Reassigning ref variable instead of its value
  • Forgetting to use .value to access ref
  • Assuming reactive is needed instead of ref
5. You want to create a composable that fetches user data and exposes loading state. Which approach correctly combines reactive state and async fetch inside a composable?
hard
A. function useUser() { const user = ref(null); const loading = ref(true); async function fetchUser() { loading.value = true; user.value = await fetch('/api/user').then(r => r.json()); loading.value = false; } fetchUser(); return { user, loading }; }
B. function useUser() { const user = reactive(null); const loading = false; async function fetchUser() { loading = true; user = await fetch('/api/user').then(r => r.json()); loading = false; } fetchUser(); return { user, loading }; }
C. function useUser() { const user = ref(null); const loading = ref(false); function fetchUser() { loading.value = true; fetch('/api/user').then(r => r.json()).then(data => { user.value = data; loading.value = false; }); } return { user, loading, fetchUser }; }
D. function useUser() { const user = ref(null); const loading = ref(true); fetch('/api/user').then(r => r.json()).then(data => { user = data; loading.value = false; }); return { user, loading }; }

Solution

  1. Step 1: Check reactive state initialization

    function useUser() { const user = ref(null); const loading = ref(true); async function fetchUser() { loading.value = true; user.value = await fetch('/api/user').then(r => r.json()); loading.value = false; } fetchUser(); return { user, loading }; } correctly uses ref for user and loading states.
  2. Step 2: Verify async fetch and state updates

    function useUser() { const user = ref(null); const loading = ref(true); async function fetchUser() { loading.value = true; user.value = await fetch('/api/user').then(r => r.json()); loading.value = false; } fetchUser(); return { user, loading }; } uses async function to set loading true, await fetch, then set loading false.
  3. Step 3: Confirm fetch is called inside composable

    function useUser() { const user = ref(null); const loading = ref(true); async function fetchUser() { loading.value = true; user.value = await fetch('/api/user').then(r => r.json()); loading.value = false; } fetchUser(); return { user, loading }; } calls fetchUser() immediately to start loading data.
  4. Final Answer:

    function useUser() { const user = ref(null); const loading = ref(true); async function fetchUser() { loading.value = true; user.value = await fetch('/api/user').then(r => r.json()); loading.value = false; } fetchUser(); return { user, loading }; } -> Option A
  5. Quick Check:

    Async fetch with reactive refs = A [OK]
Hint: Use ref for state and async function with await inside composable [OK]
Common Mistakes:
  • Reassigning reactive or ref variables directly
  • Not using async/await properly
  • Not updating loading state correctly
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