Hone logo
Hone
Problems

Progressive Enhancement for a React Comment Section

This challenge focuses on building a React component that demonstrates progressive enhancement. The goal is to create a comment section that provides a basic, functional experience for users with JavaScript disabled or not fully loaded, while offering an enhanced, interactive experience for users with JavaScript enabled.

Problem Description

You need to build a CommentSection React component in TypeScript that displays a list of comments and allows users to add new comments.

Key Requirements:

  1. Basic Functionality (No JavaScript):

    • When JavaScript is disabled or fails to load, the comment section should still be rendered.
    • Comments should be displayed.
    • A form to add a new comment (input field and submit button) should be visible.
    • Submitting the form should trigger a traditional, non-AJAX form submission, likely causing a page reload to display the new comment.
  2. Enhanced Functionality (With JavaScript):

    • When JavaScript is enabled, the comment section should be interactive.
    • Comments should be displayed.
    • A form to add a new comment should be present.
    • Submitting the form should use AJAX (e.g., fetch API) to send the new comment data to a hypothetical backend endpoint.
    • Upon successful AJAX submission, the new comment should be added to the displayed list without a full page reload.
    • The form should be cleared after a successful submission.
    • Display an error message if the AJAX submission fails.
  3. Component Structure:

    • Create a CommentSection component that accepts an initial array of Comment objects as a prop.
    • Define a Comment interface/type.
    • Create separate components for CommentList and CommentForm.

Expected Behavior:

  • User with JavaScript Disabled: Sees comments, fills out the form, clicks submit, and the page reloads with the new comment.
  • User with JavaScript Enabled: Sees comments, fills out the form, clicks submit. The form data is sent via AJAX. The new comment appears instantly in the list, and the form clears. If an error occurs during AJAX, an error message is shown.

Edge Cases:

  • What happens if the initial data loading fails (though for this challenge, assume initial data is provided as a prop)?
  • What if the form submission fails on the server-side (even with AJAX)? The UI should reflect this.
  • Consider handling potentially long comment texts.

Examples

Let's assume a Comment object has id (string), author (string), and text (string) properties.

Example 1: Initial Load (JavaScript Enabled)

// Props
initialComments = [
  { id: "c1", author: "Alice", text: "Great post!" },
  { id: "c2", author: "Bob", text: "Thanks for sharing." }
];

// Rendered UI
-------------------------
Comments:
- Alice: Great post!
- Bob: Thanks for sharing.

Add a Comment:
[ Input field for author ]
[ Input field for comment text ]
[ Submit Button ]
-------------------------

Example 2: Adding a Comment (JavaScript Enabled, Successful AJAX)

  1. User input:
    • Author: "Charlie"
    • Text: "I agree!"
  2. AJAX Request: POST /api/comments with { author: "Charlie", text: "I agree!" }
  3. Hypothetical Server Response: { id: "c3", author: "Charlie", text: "I agree!" } (with status 201 Created)
// Updated UI (without page reload)
-------------------------
Comments:
- Alice: Great post!
- Bob: Thanks for sharing.
- Charlie: I agree!

Add a Comment:
[ Input field for author (empty) ]
[ Input field for comment text (empty) ]
[ Submit Button ]
-------------------------

Example 3: Adding a Comment (JavaScript Enabled, AJAX Failure)

  1. User input:
    • Author: "David"
    • Text: "Something went wrong."
  2. AJAX Request: POST /api/comments with { author: "David", text: "Something went wrong." }
  3. Hypothetical Server Response: Error (e.g., network issue, server error)
// Updated UI
-------------------------
Comments:
- Alice: Great post!
- Bob: Thanks for sharing.

Add a Comment:
[ Input field for author ]
[ Input field for comment text ]
[ Submit Button ]
Error: Failed to submit comment. Please try again later.
-------------------------

Example 4: Submitting Form (JavaScript Disabled)

  1. User input:
    • Author: "Eve"
    • Text: "This works offline too!"
  2. Form Submission: Traditional HTML form submission to a server endpoint (e.g., POST /comments) with author=Eve&text=This+works+offline+too!. This would typically cause a page reload, and the server would need to handle this submission and re-render the page with "Eve: This works offline too!" as a new comment. The UI presented here is illustrative of what the user sees before and after the reload.
// UI before submit (JavaScript Disabled)
-------------------------
Comments:
- Alice: Great post!
- Bob: Thanks for sharing.

Add a Comment:
[ Input field for author: Eve ]
[ Input field for comment text: This works offline too! ]
[ Submit Button ]
-------------------------

// UI after page reload (assuming successful server-side processing)
-------------------------
Comments:
- Alice: Great post!
- Bob: Thanks for sharing.
- Eve: This works offline too!

Add a Comment:
[ Input field for author ]
[ Input field for comment text ]
[ Submit Button ]
-------------------------

Constraints

  • The CommentSection component should be designed to work with and without client-side JavaScript.
  • Simulate AJAX calls using the fetch API or XMLHttpRequest. You do not need a real backend; you can mock the network responses.
  • The submission endpoint for AJAX should be assumed to be /api/comments (POST).
  • The submission endpoint for non-JavaScript fallback should be assumed to be /comments (POST).
  • You can use Math.random().toString(36).substring(7) to generate unique IDs for new comments if needed for client-side state management.
  • Assume a maximum of 50 comments will be initially displayed.
  • The comment text should not exceed 280 characters for display purposes (though the input itself can be longer).

Notes

  • The core of this challenge is to ensure the component renders and functions in a degraded environment.
  • Consider how you might detect if JavaScript is enabled. A common pattern is to have a "hydration" step or a component that only renders its interactive parts when JS is available, and a fallback HTML structure is always present.
  • Think about using conditional rendering based on a state variable that indicates whether client-side interactivity is active.
  • For simulating the non-JavaScript fallback, you can either wrap the entire form submission logic in a check, or design the initial HTML to be non-interactive and then "upgrade" it with JavaScript. The latter is a more robust progressive enhancement approach.
  • You'll need to manage the state of the comments locally within the CommentSection component when JavaScript is enabled.
Loading editor...
typescript