Hone logo
Hone
Problems

Building a Dynamic User Profile Card with Reactive Props

This challenge focuses on leveraging Vue.js's reactivity system to create a reusable and dynamic UserProfileCard component. You will learn how to pass data to a component via props and ensure that any changes to these props automatically update the component's displayed information. This is fundamental for building interactive user interfaces in Vue.

Problem Description

Your task is to create a Vue.js component named UserProfileCard that displays user information. This component will receive user data as props. The challenge lies in making these props "reactive," meaning that if the data passed to the UserProfileCard from its parent component changes, the UserProfileCard should automatically reflect these updates without requiring manual re-rendering logic within the card itself.

Key Requirements:

  1. Create a UserProfileCard component: This component should accept the following props:
    • name: A string representing the user's full name.
    • avatarUrl: A string representing the URL of the user's avatar image.
    • bio: A string providing a short biography of the user.
    • followers: A number representing the user's follower count.
    • following: A number representing the user's following count.
  2. Display the props: Inside the UserProfileCard component's template, display the received prop data in a visually appealing card format.
    • The avatar should be displayed using an <img> tag.
    • The name, bio, followers, and following counts should be displayed as text.
  3. Ensure Reactivity: Any changes made to the props passed from the parent component to the UserProfileCard must automatically update the displayed information within the card.
  4. Use TypeScript: Implement the component using Vue's <script setup> syntax with TypeScript.

Expected Behavior:

When the parent component renders the UserProfileCard with initial user data, the card should display that data correctly. If the parent component updates any of the props (e.g., changes the name or increments followers), the UserProfileCard should immediately update its display to reflect these new values.

Edge Cases to Consider:

  • Missing avatarUrl: If avatarUrl is not provided, display a placeholder or default avatar.
  • Empty bio: If bio is an empty string, handle it gracefully (e.g., display a "No bio available" message).

Examples

Example 1:

Parent Component (Simplified):

<template>
  <UserProfileCard
    name="Alice Wonderland"
    avatarUrl="https://example.com/avatars/alice.png"
    bio="Curiouser and curiouser!"
    :followers="1500"
    :following="250"
  />
</template>

<script setup lang="ts">
import UserProfileCard from './UserProfileCard.vue';
</script>

UserProfileCard Component Output:

<div class="user-profile-card">
  <img src="https://example.com/avatars/alice.png" alt="Alice Wonderland avatar" class="avatar">
  <h2>Alice Wonderland</h2>
  <p>Curiouser and curiouser!</p>
  <div class="stats">
    <span>Followers: 1500</span>
    <span>Following: 250</span>
  </div>
</div>

Explanation: The UserProfileCard component receives the provided props and renders them within its structure.

Example 2:

Parent Component (with prop updates):

<template>
  <UserProfileCard
    :name="currentUser.name"
    :avatarUrl="currentUser.avatarUrl"
    :bio="currentUser.bio"
    :followers="currentUser.followers"
    :following="currentUser.following"
  />
  <button @click="updateUser">Update User</button>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import UserProfileCard from './UserProfileCard.vue';

const currentUser = ref({
  name: 'Bob The Builder',
  avatarUrl: 'https://example.com/avatars/bob.png',
  bio: 'Can we fix it? Yes, we can!',
  followers: 5000,
  following: 100,
});

const updateUser = () => {
  currentUser.value = {
    name: 'Bob The Renovator',
    avatarUrl: 'https://example.com/avatars/bob_renovator.png',
    bio: 'Making old things new again.',
    followers: 5500,
    following: 120,
  };
};
</script>

UserProfileCard Component Output (before button click):

<div class="user-profile-card">
  <img src="https://example.com/avatars/bob.png" alt="Bob The Builder avatar" class="avatar">
  <h2>Bob The Builder</h2>
  <p>Can we fix it? Yes, we can!</p>
  <div class="stats">
    <span>Followers: 5000</span>
    <span>Following: 100</span>
  </div>
</div>

UserProfileCard Component Output (after button click):

<div class="user-profile-card">
  <img src="https://example.com/avatars/bob_renovator.png" alt="Bob The Renovator avatar" class="avatar">
  <h2>Bob The Renovator</h2>
  <p>Making old things new again.</p>
  <div class="stats">
    <span>Followers: 5500</span>
    <span>Following: 120</span>
  </div>
</div>

Explanation: The currentUser object in the parent is reactive. When the updateUser function is called, the currentUser ref is updated. Because UserProfileCard receives these values as props, it automatically re-renders to display the new user information.

Example 3: Handling Missing Avatar

Parent Component:

<template>
  <UserProfileCard
    name="Anonymous User"
    bio="Just passing by."
    :followers="10"
    :following="5"
  />
</template>

<script setup lang="ts">
import UserProfileCard from './UserProfileCard.vue';
</script>

UserProfileCard Component Output:

<div class="user-profile-card">
  <img src="/path/to/default-avatar.png" alt="Anonymous User avatar" class="avatar"> <!-- Assuming a default path -->
  <h2>Anonymous User</h2>
  <p>Just passing by.</p>
  <div class="stats">
    <span>Followers: 10</span>
    <span>Following: 5</span>
  </div>
</div>

Explanation: When avatarUrl is not provided, the component renders a default avatar image.

Constraints

  • The UserProfileCard component must be implemented using Vue 3 with the Composition API and <script setup>.
  • TypeScript must be used for type safety.
  • Props should be declared using defineProps.
  • The styling of the card is not a primary concern for this challenge, but it should be presentable. Basic CSS for layout and visual separation is acceptable.
  • The parent component can be a simple Vue component that demonstrates passing and updating props.

Notes

  • Vue's prop system is inherently reactive. When you pass a prop to a child component, Vue automatically tracks changes to that prop. If the parent component updates the data that's being passed down, the child component will re-render to reflect those changes.
  • For the "missing avatar" edge case, you can either import a default avatar image into your UserProfileCard component or provide a placeholder URL.
  • Consider using computed properties if you need to derive any values based on the props within the UserProfileCard component, though for this specific challenge, direct prop usage is sufficient.
  • Focus on the fundamental mechanism of passing and updating props for reactivity.
Loading editor...
typescript