A composable with reactive state helps you organize and reuse reactive data and logic in Vue components easily.
Composable with reactive state in Vue
import { ref } from 'vue'; export function useExample(initialValue) { const state = ref(initialValue); function updateState(newValue) { state.value = newValue; } return { state, updateState }; }
Use ref to create reactive state that updates the UI automatically.
Return the reactive state and functions so components can use them.
import { ref } from 'vue'; export function useCounter() { const count = ref(0); function increment() { count.value++; } return { count, increment }; }
reactive for an object state with multiple properties.import { reactive } from 'vue'; export function useUser() { const user = reactive({ name: '', age: 0 }); function updateName(newName) { user.name = newName; } return { user, updateName }; }
This Vue component uses a composable useToggle to manage a reactive boolean state. Clicking the button toggles the state between ON and OFF.
<script setup> import { ref } from 'vue'; function useToggle() { const isOn = ref(false); function toggle() { isOn.value = !isOn.value; } return { isOn, toggle }; } const { isOn, toggle } = useToggle(); </script> <template> <button @click="toggle" :aria-pressed="isOn"> {{ isOn ? 'ON' : 'OFF' }} </button> </template>
Always return reactive state and functions from composables to keep logic reusable.
Use ref for simple values and reactive for objects.
Composable functions should start with use to follow Vue conventions.
Composable functions help reuse reactive state and logic across components.
Use ref or reactive to create reactive state inside composables.
Return state and functions from composables so components can use them easily.
Practice
Solution
Step 1: Understand composable function role
Composable functions are designed to share reactive state and logic so multiple components can use them without repeating code.Step 2: Eliminate unrelated options
Creating new Vue components automatically, defining global CSS styles for the app, and replacing the Vue router functionality are all unrelated to composables.Final Answer:
To reuse reactive state and logic across multiple components -> Option DQuick Check:
Composable = reusable reactive logic [OK]
- Confusing composables with components
- Thinking composables handle styling or routing
- Assuming composables create UI elements
Solution
Step 1: Recall ref and reactive usage
refis used to create a reactive primitive like a number, string, or boolean.reactiveis for objects.Step 2: Analyze options
const count = ref(0) correctly usesref(0)for a reactive number. const count = reactive(0) is invalid becausereactiveexpects an object, not a primitive. const count = reactive({ value: 0 }) wraps a number in an object but is less common for simple primitives. const count = ref({ value: 0 }) usesrefwith an object, which works but is less idiomatic thanreactivefor objects.Final Answer:
const count = ref(0) -> Option BQuick Check:
Primitive reactive state uses ref() [OK]
- Using reactive() with primitive values
- Using ref() for complex objects instead of reactive()
- Confusing ref({}) and reactive({}) usage
increment() is called twice and then count.value is logged?import { ref } from 'vue';
export function useCounter() {
const count = ref(0);
function increment() {
count.value++;
}
return { count, increment };
}
const { count, increment } = useCounter();
increment();
increment();
console.log(count.value);Solution
Step 1: Understand initial state and increments
The count starts at 0. Each call to increment() increases count.value by 1.Step 2: Calculate final value after two increments
After two calls, count.value = 0 + 1 + 1 = 2.Final Answer:
2 -> Option AQuick Check:
Two increments add 2 to count.value [OK]
- Forgetting to access .value on ref
- Assuming count is a plain number, not ref
- Confusing initial value with updated value
import { reactive } from 'vue';
export function useUser() {
const user = reactive({ name: 'Alice', age: 30 });
function updateName(newName) {
user.name = newName;
}
return { user, updateName };
}
const { user, updateName } = useUser();
updateName('Bob');
console.log(user.name);Solution
Step 1: Check reactive object usage
Theuserobject is created withreactiveand its properties can be updated directly.Step 2: Verify function and return
TheupdateNamefunction updatesuser.namecorrectly and is returned for use.Final Answer:
No error, code works correctly -> Option AQuick Check:
Reactive objects allow direct property assignment [OK]
- Thinking reactive properties are read-only
- Forgetting to return functions from composable
- Confusing ref and reactive usage
Solution
Step 1: Choose correct reactive type for array
Arrays as reactive state are best handled withref([])so we access the array viatasks.value.Step 2: Validate addTask function logic
import { ref } from 'vue'; export function useTasks() { const tasks = ref([]); function addTask(task) { if (task) tasks.value.push(task); } return { tasks, addTask }; } checks iftaskis truthy (not empty) before pushing totasks.value, which is correct. import { reactive } from 'vue'; export function useTasks() { const tasks = reactive([]); function addTask(task) { if (task) tasks.value.push(task); } return { tasks, addTask }; } usesreactive([])but incorrectly accessestasks.value.push(task)since reactive does not have avalueproperty. import { ref } from 'vue'; export function useTasks() { const tasks = ref([]); function addTask(task) { tasks.push(task); } return { tasks, addTask }; } pushes without checking if task is empty. import { reactive } from 'vue'; export function useTasks() { const tasks = reactive([]); function addTask(task) { if (task.length > 0) tasks.value.push(task); } return { tasks, addTask }; } incorrectly tries to accesstasks.valuewhentasksis reactive, which does not have avalueproperty.Final Answer:
use ref([]) with if (task) tasks.value.push(task) -> Option CQuick Check:
Use ref([]) for arrays and check input before push [OK]
- Using reactive([]) for arrays instead of ref([])
- Forgetting to check if task is empty
- Accessing .value on reactive arrays
Ready to prove it?
Pass the test and this pattern moves unknown
