Bird
Raised Fist0
Vueframework~8 mins

Sharing composables across components in Vue - Performance & Optimization

Choose your learning style10 modes available
Performance: Sharing composables across components
MEDIUM IMPACT
This affects how efficiently state and logic are reused across Vue components, impacting rendering speed and memory usage.
Sharing reactive state logic between multiple components
Vue
const sharedCount = ref(0);
function useCounter() {
  function increment() {
    sharedCount.value++;
  }
  return { count: sharedCount, increment };
}

// In each component
const { count, increment } = useCounter();
All components share the same reactive state, reducing memory and syncing updates efficiently.
📈 Performance GainSaves memory by sharing one reactive object; reduces redundant re-renders.
Sharing reactive state logic between multiple components
Vue
function useCounter() {
  const count = ref(0);
  function increment() {
    count.value++;
  }
  return { count, increment };
}

// In each component
const { count, increment } = useCounter();
Each component creates its own separate reactive state, causing duplicated memory and no shared updates.
📉 Performance CostIncreases memory usage linearly with components; triggers independent reactivity and re-renders.
Performance Comparison
PatternDOM OperationsReflowsPaint CostVerdict
Separate reactive state per componentMultiple reactive refs per componentMultiple re-renders on updatesHigher paint cost due to many updates[X] Bad
Shared reactive state via composableSingle reactive ref sharedSingle re-render per updateLower paint cost with fewer updates[OK] Good
Rendering Pipeline
When composables are shared properly, Vue reactivity tracks a single source of truth, minimizing redundant reactive updates and re-renders.
→Reactive Dependency Tracking
→Component Render
→DOM Update
⚠️ BottleneckExcessive reactive state duplication causes more dependency tracking and component re-renders.
Core Web Vital Affected
INP
This affects how efficiently state and logic are reused across Vue components, impacting rendering speed and memory usage.
Optimization Tips
1Avoid creating new reactive state inside composables for each component if shared state is intended.
2Use shared refs or stores to centralize reactive data across components.
3Monitor component re-renders in DevTools to detect unnecessary reactive duplication.
Performance Quiz - 3 Questions
Test your performance knowledge
What is the main performance issue when each component creates its own reactive state from a composable?
ACSS styles are recalculated unnecessarily
BThe app bundle size grows significantly
CMemory usage increases and components re-render independently
DThe browser blocks rendering on network requests
DevTools: Performance
How to check: Record a performance profile while interacting with components using the composable. Look for repeated reactive updates and component re-renders.
What to look for: High number of component renders or reactive effect recalculations indicates duplicated state; fewer renders means better sharing.

Practice

(1/5)
1. What is the main purpose of a composable in Vue 3?
function useCounter() { const count = ref(0); return { count }; }
easy
A. To register global Vue directives
B. To define a new component template
C. To style components with CSS
D. To share reusable reactive logic across multiple components

Solution

  1. Step 1: Understand what a composable function does

    A composable is a function that returns reactive state or methods to be reused.
  2. Step 2: Identify the purpose of the example composable

    The example returns a reactive count variable to share logic across components.
  3. Final Answer:

    To share reusable reactive logic across multiple components -> Option D
  4. Quick Check:

    Composable = reusable logic [OK]
Hint: Composable functions return reactive state for reuse [OK]
Common Mistakes:
  • Thinking composables define templates
  • Confusing composables with CSS styling
  • Assuming composables register directives
2. Which is the correct way to import and use a composable named useTimer inside a Vue component's setup() function?
easy
A. import { useTimer } from './composables'; const { time } = useTimer();
B. import useTimer from './composables'; const time = useTimer;
C. const useTimer = require('./composables'); const { time } = useTimer();
D. import useTimer from './composables'; setup() { return useTimer; }

Solution

  1. Step 1: Import the composable correctly

    Use ES module import syntax with curly braces if composable is a named export.
  2. Step 2: Call the composable function inside setup()

    Call useTimer() to get reactive state, then destructure needed properties.
  3. Final Answer:

    import { useTimer } from './composables'; const { time } = useTimer(); -> Option A
  4. Quick Check:

    Import named + call function = correct usage [OK]
Hint: Import named composable and call it inside setup() [OK]
Common Mistakes:
  • Using require() instead of import
  • Not calling the composable function
  • Importing default when composable is named export
3. Given this composable and component code, what will be logged?
// composable.js
import { ref } from 'vue';
export function useCount() {
  const count = ref(0);
  function increment() { count.value++; }
  return { count, increment };
}

// Component.vue
import { useCount } from './composable';
export default {
  setup() {
    const { count, increment } = useCount();
    increment();
    increment();
    console.log(count.value);
    return {};
  }
}
medium
A. 2
B. 0
C. undefined
D. Error: count is not defined

Solution

  1. Step 1: Analyze composable logic

    Count starts at 0 and increments by 1 each time increment() is called.
  2. Step 2: Trace component setup execution

    Increment is called twice, so count.value becomes 2, then logged.
  3. Final Answer:

    2 -> Option A
  4. Quick Check:

    Two increments = count 2 [OK]
Hint: Count increments twice, so value is 2 [OK]
Common Mistakes:
  • Forgetting to call increment()
  • Confusing ref with plain variable
  • Expecting count to be 0 without increments
4. Identify the error in this composable usage:
import { ref } from 'vue';
export function useData() {
  const data = ref(null);
  fetch('/api').then(res => res.json()).then(json => data = json);
  return { data };
}
medium
A. Using ref instead of reactive
B. Missing await keyword before fetch
C. Reassigning the ref variable instead of its value
D. Not returning the data variable

Solution

  1. Step 1: Check how ref is updated

    Ref variables must update their .value, not be reassigned.
  2. Step 2: Identify the mistake in the fetch callback

    The code assigns data = json instead of data.value = json.
  3. Final Answer:

    Reassigning the ref variable instead of its value -> Option C
  4. Quick Check:

    Update ref.value, not ref itself [OK]
Hint: Update ref.value, not the ref variable [OK]
Common Mistakes:
  • Assigning directly to ref variable
  • Forgetting to handle async properly
  • Confusing reactive with ref usage
5. You want to share a composable that tracks a user's online status across multiple components. Which approach ensures each component has its own independent reactive state?
hard
A. Export a single reactive object and import it directly in all components
B. Export a function that returns new refs each call, then import and call it in each component
C. Define reactive state inside a global variable outside the composable
D. Use a Vuex store instead of composables for reactive state

Solution

  1. Step 1: Understand independent reactive state per component

    Each component needs its own fresh reactive refs to avoid shared state.
  2. Step 2: Identify correct composable pattern

    Exporting a function that returns new refs each call creates isolated state per component.
  3. Final Answer:

    Export a function that returns new refs each call, then import and call it in each component -> Option B
  4. Quick Check:

    Function returns fresh state per call [OK]
Hint: Return new refs inside function for isolated state [OK]
Common Mistakes:
  • Sharing a single reactive object causing shared state
  • Using global variables outside composables
  • Confusing Vuex with composables for local state
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