Hone logo
Hone
Problems

Vue Store Hydration with Pinia

This challenge focuses on a common and crucial aspect of modern Vue applications: ensuring your application's state is correctly loaded and available when the user first accesses a protected route or when the application loads. You will implement a mechanism to "hydrate" a Pinia store with initial data, simulating scenarios like fetching user data after authentication or pre-loading essential application settings.

Problem Description

Your task is to build a system that allows a Pinia store to be "hydrated" with initial data. This is particularly useful when an application needs to load data before rendering the main UI, such as fetching user profiles, authentication tokens, or application configurations from an API or local storage.

Key Requirements:

  • Asynchronous Hydration: The hydration process should be asynchronous, allowing for data fetching operations (e.g., API calls).
  • Store Initialization: The hydrated data should populate the state of a Pinia store.
  • Conditional Rendering/Navigation: Components should ideally wait for the store to be hydrated before rendering sensitive content or navigating to certain routes.
  • Error Handling: The hydration process should include basic error handling mechanisms.

Expected Behavior:

  1. When the application starts or a specific route is accessed, a hydration action is triggered.
  2. This action attempts to fetch initial data.
  3. If successful, the data is used to update the Pinia store's state.
  4. If an error occurs during fetching, an appropriate error state is set in the store, or an error is thrown to be caught by a higher-level mechanism.
  5. Components that depend on the hydrated data should either display a loading state or wait until the data is available.

Edge Cases:

  • What happens if the data fetching fails?
  • What if the data is already present (e.g., from a server-side rendered page or previous session)? (For this challenge, assume we are always fetching fresh data or simulating a first-time load).
  • Handling different types of initial data (e.g., user object, boolean flags, configuration settings).

Examples

Example 1: Hydrating User Data

// Initial State (before hydration)
// userStore: { user: null, isLoading: false, error: null }

// Action: hydrateUser
// Simulates fetching user data from an API.
// Returns a Promise that resolves with a user object.

// After successful hydration:
// userStore: { user: { id: 1, name: 'Alice' }, isLoading: false, error: null }

Explanation: The hydrateUser action is called. It sets isLoading to true, fetches user data (simulated), and upon success, updates the user state and sets isLoading to false.

Example 2: Hydration with No Data

// Initial State (before hydration)
// appConfigStore: { settings: null, isLoading: false, error: null }

// Action: hydrateConfig
// Simulates fetching configuration, but API returns no relevant data.

// After successful hydration (but no data found):
// appConfigStore: { settings: null, isLoading: false, error: null }

Explanation: The hydrateConfig action runs, but the simulated API call returns null or an empty object. The store correctly reflects that no settings were loaded, without setting an error.

Example 3: Hydration Failure

// Initial State (before hydration)
// sessionStore: { isAuthenticated: false, isLoading: false, error: null }

// Action: hydrateSession
// Simulates fetching session data, but API returns an error (e.g., network issue).

// After failed hydration:
// sessionStore: { isAuthenticated: false, isLoading: false, error: 'Failed to fetch session' }

Explanation: The hydrateSession action attempts to fetch data. An error occurs during the simulated fetch. The error state in the store is updated, and isLoading is set to false.

Constraints

  • The solution must use Vue 3 and Pinia.
  • All store definitions, actions, and relevant components should be written in TypeScript.
  • The hydration logic should be encapsulated within a Pinia action.
  • Assume a simulated asynchronous operation for data fetching (e.g., using setTimeout to mimic network latency).
  • Focus on the hydration mechanism itself, not complex routing or component lifecycle management for waiting.

Notes

  • Consider how you might signal to your application that hydration is complete. This could be through a boolean flag in the store or a dedicated event.
  • Think about how this hydration process would integrate with Vue Router's navigation guards or the app.mount() lifecycle if you were building a full application.
  • For this challenge, you don't need to implement a full Vue application structure. Focus on defining a Pinia store with a hydration action and demonstrating its usage.
  • You can use mock data or simple Promise.resolve() and Promise.reject() for simulating API responses.
Loading editor...
typescript