tezvyn:

How would you design useCounter to support shared or independent state?

AI-drafted, machine-checkedSource: vuejs.orgadvanced

Tests your grasp of scope in Vue composables. Great answers contrast module-level refs for global singleton state against function-level refs for per-instance isolation, and explain tradeoffs.

WHAT THIS TESTS: This question tests your understanding of JavaScript lexical scope and Vue's Composition API reactivity system. Specifically, it checks whether you know that reactive state declared at module scope lives once per module import, while state declared inside a composable function body is recreated on every function invocation. It also tests whether you understand the architectural implications of shared versus instance-local state and whether you can articulate when to choose one over the other without immediately reaching for external libraries or complex patterns.

A GOOD ANSWER COVERS: First, the instance-scoped pattern: define ref or reactive variables inside the useCounter function body so each component that calls it receives a fresh independent state object. Second, the singleton pattern: move those same reactive declarations outside the function to module scope so every component shares the exact same reactive object and mutations propagate everywhere. Third, explain the tradeoffs: module-scoped state is simpler for true global concerns like a shopping cart or authentication status, but it requires careful cleanup because lifecycle hooks like onUnmounted tied to module scope can behave unexpectedly when the last consumer unmounts. Fourth, mention that you can expose a factory or accept an options argument if you want the caller to decide, though most composables pick one pattern based on intent and naming conventions.

COMMON WRONG ANSWERS: A red flag is suggesting Pinia, provide and inject, or props as the primary way to toggle between shared and independent state. Those are valid tools for other problems, but they miss the point that this is fundamentally about where you declare variables. Another red flag is claiming that refs are always shared or always isolated without explaining the role of scope. Candidates who forget that module-level event listeners or intervals survive component unmounts also reveal shallow understanding of side effect ownership.

LIKELY FOLLOW-UPS: The interviewer might ask how you would clean up side effects in a module-scoped singleton, such as using a reference counter to detach a window listener only when the last component unmounts. They might also ask how to make the pattern configurable, for example by accepting a unique key parameter to create a registry of named shared states rather than a single global singleton, which is useful for multi-tenant or namespaced state.

ONE CONCRETE EXAMPLE: For a shared counter, declare const count = ref(0) and const increment = () => count.value++ at the top level of the file, then return them from useCounter. For an independent counter, move const count = ref(0) inside the useCounter function so each component gets its own count. If three components use the shared version, clicking increment in any one updates all three displays. If they use the instance version, each click affects only that component's local display.

Read the original → vuejs.org

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.