Bird
Raised Fist0
Vueframework~10 mins

Why composables matter in Vue - Visual Breakdown

Choose your learning style10 modes available
Concept Flow - Why composables matter
Start: Need reusable logic
↓
Create composable function
↓
Use composable in components
↓
Share state and behavior
↓
Simplify components
↓
Easier testing and maintenance
↓
End
This flow shows how composables help by extracting reusable logic into functions that components can share, making code simpler and easier to maintain.
Execution Sample
Vue
import { ref } from 'vue'

export function useCounter() {
  const count = ref(0)
  function increment() {
    count.value++
  }
  return { count, increment }
}
This composable provides a counter state and an increment function to be reused in multiple components.
Execution Table
StepActionState BeforeState AfterOutput/Effect
1Call useCounter()No countcount = 0Composable initialized with count 0
2Call increment()count = 0count = 1Count increased to 1
3Call increment()count = 1count = 2Count increased to 2
4Return { count, increment }count = 2count = 2Composable returns reactive state and function
5Component uses composableNo local countcount reactive linkedComponent can display and update count
6Another component calls useCounter()No countcount = 0New independent count state created
7Call increment() in second componentcount = 0count = 1Second component count increases independently
💡 Execution stops after composable returns and components use independent reactive states.
Variable Tracker
VariableStartAfter 1After 2After 3Final
count (first composable)undefined0122
count (second composable)undefined0011
Key Moments - 2 Insights
Why does each component get its own count value when using the same composable?
Because the composable function creates a new reactive count variable each time it is called, as shown in execution_table rows 1 and 6.
What happens if we don't return the count and increment from the composable?
The component cannot access or update the count state, so the composable would not be useful. See execution_table row 4 where the return enables usage.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution_table at step 3, what is the value of count after increment() is called the second time?
A2
B0
C1
D3
💡 Hint
Check the 'State After' column in execution_table row 3.
At which step does the second component get its own independent count state?
AStep 2
BStep 6
CStep 5
DStep 7
💡 Hint
Look for when useCounter() is called again for a new component in execution_table.
If the composable did not return the increment function, what would happen in the component?
Acount would not be reactive
BComponent could still update count directly
CComponent could not update count
DComponent would get an error immediately
💡 Hint
Refer to execution_table row 4 about what is returned from the composable.
Concept Snapshot
Why Composables Matter in Vue:
- Composables are functions that hold reusable reactive logic.
- Each call creates independent reactive state.
- Components use composables to share behavior simply.
- Returning state and functions enables interaction.
- They simplify code and improve maintainability.
Full Transcript
Composables in Vue are special functions that let you reuse reactive logic across components. When you call a composable, it creates its own reactive state, like a counter starting at zero. You can then use functions it returns to update that state. Each component calling the composable gets its own separate state, so they don't interfere. This helps keep components simple and makes code easier to maintain and test. The example shows a useCounter composable that returns a count and an increment function. Calling increment increases the count. Components use this composable to share the counting logic without repeating code.

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