Hone logo
Hone
Problems

Vue 3: Creating Immutable Reactive State

This challenge focuses on creating and managing reactive state in Vue 3 using TypeScript, specifically emphasizing the creation of read-only references. Understanding how to make reactive data immutable is crucial for building robust and predictable applications, preventing accidental state mutations and improving code maintainability.

Problem Description

Your task is to create a Vue 3 component that manages a piece of reactive state which should never be directly modified by the component's template or script. This immutable state should be exposed to the template for display purposes only.

Key Requirements:

  1. Declare a reactive ref: Use Vue 3's ref function to declare a reactive variable.
  2. Make the ref read-only: Ensure that the declared ref cannot be reassigned or have its .value property modified.
  3. Display the value: The template should be able to read and display the current value of the read-only ref.
  4. Demonstrate immutability: Attempting to modify the ref from the script should result in an error or no-op, clearly indicating its read-only nature.

Expected Behavior:

  • The component should successfully display the initial value of the read-only ref.
  • Any attempt to change the .value of the read-only ref within the component's script or template should be prevented.
  • The component should gracefully handle the immutability, potentially logging an error or warning if an attempt to mutate is made.

Edge Cases:

  • Consider how to handle initial null or undefined values if applicable (though for this challenge, a simple initial value is sufficient).

Examples

Example 1:

// In your Vue component's setup function
import { ref, readonly } from 'vue';

const count = ref(0);
const readOnlyCount = readonly(count); // This is what you need to achieve

// In the template:
// <template>
//   <div>Current Count: {{ readOnlyCount }}</div>
// </template>

Output:

The template will display "Current Count: 0".

Explanation:

We created a mutable ref named count. Then, using readonly(), we created readOnlyCount, which is a read-only proxy of the original count ref. The template can display readOnlyCount because it can read its value.

Example 2:

// In your Vue component's setup function
import { ref, readonly } from 'vue';

const userName = ref('Alice');
const readOnlyUserName = readonly(userName);

// In the template:
// <template>
//   <div>Hello, {{ readOnlyUserName }}!</div>
//   <button @click="tryToChangeName">Change Name</button>
// </template>

// In the script:
// const tryToChangeName = () => {
//   try {
//     readOnlyUserName.value = 'Bob'; // This line should cause an error or be a no-op
//     console.log('Name changed successfully (this should not happen)');
//   } catch (e) {
//     console.error('Error attempting to change read-only ref:', e.message);
//   }
// };

Output:

The template will display "Hello, Alice!". When the "Change Name" button is clicked, an error will be logged to the console, indicating an attempt to mutate a read-only ref. The displayed name will remain "Alice".

Explanation:

The readOnlyUserName is a Readonly<Ref<string>>. Attempting to assign a new value to its .value property will result in a runtime error (or be ignored in non-strict environments), demonstrating its immutable nature.

Constraints

  • You must use Vue 3's Composition API.
  • The solution must be implemented in TypeScript.
  • No external libraries beyond Vue 3 are permitted.
  • The primary focus is on the correct usage of ref and readonly.

Notes

  • Consider the role of readonly in managing state and preventing unintended side effects.
  • Think about how readonly differs from simply not exposing a mutation function in your component's API.
  • The readonly function itself is part of Vue 3's reactivity API.
Loading editor...
typescript