Hone logo
Hone
Problems

Building a Simple Offline-First Task List with React and LocalStorage

This challenge focuses on implementing a basic offline-first state management pattern in a React application. The goal is to create a simple task list that persists data locally using localStorage, allowing the application to function even when the user is offline. This demonstrates a fundamental concept for building robust web applications that provide a seamless user experience regardless of network connectivity.

Problem Description

You are tasked with building a React component that manages a list of tasks and persists them to localStorage. The component should allow users to:

  1. Add a new task: A text input field and an "Add Task" button should allow users to add new tasks to the list.
  2. View the task list: The current list of tasks should be displayed.
  3. Mark a task as complete: Each task should have a checkbox that, when toggled, marks the task as complete. Completed tasks should be visually distinct (e.g., strikethrough).
  4. Persist data to localStorage: The task list should be automatically saved to localStorage whenever it changes.
  5. Load data from localStorage on component mount: When the component initially mounts, it should retrieve the task list from localStorage and populate the UI.

Key Requirements:

  • Use TypeScript for type safety.
  • Utilize React state to manage the task list.
  • Employ localStorage for persistent storage.
  • Ensure the application functions correctly both online and offline.
  • Handle the case where localStorage is unavailable (e.g., due to browser settings).

Expected Behavior:

  • On initial load, the component should attempt to retrieve the task list from localStorage. If localStorage is empty or unavailable, the list should be initialized as empty.
  • Adding a new task should update the React state and immediately save the updated list to localStorage.
  • Toggling a task's completion status should update the React state and immediately save the updated list to localStorage.
  • The UI should reflect the current state of the task list, including the completion status of each task.
  • If localStorage is unavailable, an appropriate error message should be displayed to the user (e.g., "Unable to save tasks locally.").

Edge Cases to Consider:

  • localStorage is full: While unlikely in a simple task list, consider how your code might handle this (e.g., by displaying a message to the user).
  • localStorage is cleared by the user: The application should gracefully handle the loss of data.
  • Browser settings prevent localStorage usage: Provide a fallback mechanism or informative message.
  • Empty task list: The UI should handle an empty task list gracefully.

Examples

Example 1:

Input: Initial state is empty, user adds "Buy groceries" and "Walk the dog".
Output: Task list displays:
- [ ] Buy groceries
- [ ] Walk the dog
localStorage contains:  ["Buy groceries", "Walk the dog"]

Explanation: The initial state is empty. Two tasks are added, updating the state and saving to localStorage.

Example 2:

Input: localStorage contains ["Do laundry", "Pay bills"]. User marks "Do laundry" as complete.
Output: Task list displays:
- [x] Do laundry (strikethrough)
- [ ] Pay bills
localStorage contains: ["Do laundry", "Pay bills"] (The content remains the same, but the UI reflects the completed status)

Explanation: The component loads tasks from localStorage. One task is marked complete, updating the state and saving the updated list to localStorage.

Example 3:

Input: localStorage is unavailable (e.g., due to browser settings).
Output: Task list displays:
- An error message: "Unable to save tasks locally."

Explanation: The component detects that localStorage is unavailable and displays an appropriate error message.

Constraints

  • The task list should be stored as an array of strings in localStorage. Each string represents a task.
  • The application should be responsive and provide a reasonable user experience.
  • The component should be relatively simple and focused on the core offline-first functionality. No complex styling or UI frameworks are required beyond basic React components.
  • The maximum number of tasks is limited to 100. (This is a practical consideration for localStorage size, though not strictly enforced in the evaluation).

Notes

  • Consider using useEffect to handle side effects like loading and saving data to localStorage.
  • Think about how to handle errors gracefully, especially when interacting with localStorage.
  • Focus on the core logic of persisting and retrieving data. Styling and advanced UI features are not the primary focus of this challenge.
  • Use a functional component with React Hooks.
  • The key is to ensure that the task list is consistently synchronized between the React state and localStorage, providing a seamless offline experience.
Loading editor...
typescript