Question presented to candidate: "Several of our components each re-implement 'listen to window resize and clean up on unmount' and 'fetch with a loading flag'. What is a composable, how would you write one for this, and what rules does it have to follow?"
What a strong answer should cover:
- A composable is a function, named
useXby convention, that uses Composition API primitives (ref,computed,watch, lifecycle hooks) to encapsulate stateful logic and returns refs and functions. - State created inside the function is per call, so each component gets its own copy; state hoisted to module scope is shared.
- Lifecycle hooks inside a composable attach to the calling component, so cleanup (
onUnmounted,onScopeDispose) happens automatically. - Composables must be called synchronously in
setup()/<script setup>(or inside another composable or aneffectScope). - Inputs should accept a value, a ref or a getter and normalise with
toValue(); return a plain object of refs so callers can destructure. - Contrast with mixins (implicit, collision-prone) and with plain utility functions (stateless).
Clarifying questions expected:
- "Should the state be per component or shared across the app? That decides where the ref lives."
- "Does this need to run during SSR? Browser-only side effects belong in
onMounted."
Code / implementation expected: Yes β a small composable with cleanup, used by two components to show independent state.