Hone logo
Hone
Problems

Building Reusable Logic with Vue 3 Composables

This challenge focuses on implementing Vue 3 composables in TypeScript. Composables are functions that encapsulate reusable stateful logic, making your Vue applications more modular, organized, and easier to test. You will create a custom composable to manage a simple counter with increment and decrement functionality.

Problem Description

Your task is to create a Vue 3 composable function, useCounter, written in TypeScript. This composable should manage a numerical counter and provide methods to increment, decrement, and reset the counter's value.

Key Requirements:

  1. Composable Function: Create a function named useCounter.
  2. State Management: The composable must manage a reactive count variable.
  3. Methods: The composable should expose three functions:
    • increment(): Increases the count by 1.
    • decrement(): Decreases the count by 1.
    • reset(): Resets the count to an initial value.
  4. Initial Value: The useCounter composable should accept an optional initialValue argument. If not provided, it should default to 0.
  5. TypeScript: The entire implementation must be in TypeScript.
  6. Reactivity: The count must be reactive, meaning changes to it should automatically update any Vue components that use the composable.

Expected Behavior:

When useCounter is called within a Vue component:

  • The returned count should be reactive.
  • Calling increment() should increase the displayed count.
  • Calling decrement() should decrease the displayed count.
  • Calling reset() should set the count back to its initial value.

Edge Cases:

  • Handling cases where initialValue is not provided.
  • Ensuring the counter can go below zero if decremented enough.

Examples

Example 1:

// In a Vue component:
import { useCounter } from './useCounter'; // Assuming useCounter is in './useCounter.ts'

export default {
  setup() {
    const { count, increment, decrement, reset } = useCounter(5); // Initial value of 5

    return {
      count,
      increment,
      decrement,
      reset
    };
  }
}

Template:

<template>
  <div>
    <p>Count: {{ count }}</p>
    <button @click="increment">Increment</button>
    <button @click="decrement">Decrement</button>
    <button @click="reset">Reset</button>
  </div>
</template>

Explanation: The useCounter composable is initialized with 5. The component displays the count (initially 5). Clicking "Increment" will change count to 6, "Decrement" to 4, and "Reset" will bring it back to 5.

Example 2:

// In a Vue component:
import { useCounter } from './useCounter';

export default {
  setup() {
    const { count, increment, decrement, reset } = useCounter(); // No initial value provided

    return {
      count,
      increment,
      decrement,
      reset
    };
  }
}

Template:

<template>
  <div>
    <p>Count: {{ count }}</p>
    <button @click="increment">Increment</button>
    <button @click="decrement">Decrement</button>
    <button @click="reset">Reset</button>
  </div>
</template>

Explanation: When useCounter is called without an initialValue, it defaults to 0. The component will display 0 initially. Incrementing will make it 1, decrementing will make it -1, and resetting will return it to 0.

Constraints

  • The useCounter function must return an object containing count, increment, decrement, and reset.
  • The count property must be of type number.
  • The increment, decrement, and reset properties must be functions.
  • The initialValue argument, if provided, must be a number.

Notes

  • Remember to use Vue's ref function to make the count reactive.
  • Consider how you will type the return value of your composable for better TypeScript integration.
  • This challenge is designed to familiarize you with the basic structure and usage of composables.
Loading editor...
typescript