Hone logo
Hone
Problems

React Rich Text Editor Wrapper

Building a rich text editor is a complex task, but creating a reusable wrapper component in React can simplify its integration into various applications. This challenge asks you to build a React component that encapsulates a popular rich text editor library (Quill.js is suggested, but you can choose another if you prefer, clearly stating your choice) and provides a clean, type-safe interface for interacting with it. This wrapper will handle initialization, content management, and provide a controlled component experience.

Problem Description

You are tasked with creating a RichTextEditor React component in TypeScript. This component should wrap a rich text editor library (Quill.js is recommended for this challenge, but you can use another if you justify your choice). The component should:

  1. Initialization: Initialize the Quill.js editor instance when the component mounts and destroy it when the component unmounts.
  2. Controlled Component: Be a controlled component, meaning the editor's content is driven by a value prop. The value prop should be a string representing the editor's content.
  3. onChange Callback: Provide an onChange prop that is called whenever the editor's content changes. The callback should receive the new content (as a string) as an argument.
  4. Configuration: Accept a modules prop (an object conforming to Quill.js's module structure) to allow customization of the editor's features (e.g., toolbar configuration).
  5. Theme: Accept a theme prop (string) to allow customization of the editor's theme (e.g., 'snow', 'bubble').
  6. Placeholder: Accept a placeholder prop (string) to display placeholder text when the editor is empty.
  7. Error Handling: Gracefully handle potential errors during editor initialization or updates.
  8. Empty Content Handling: Correctly handle the case where the initial value prop is an empty string.

Expected Behavior:

  • The component should render a Quill.js editor within its container.
  • The editor's content should be synchronized with the value prop.
  • The onChange callback should be triggered whenever the user modifies the editor's content.
  • The editor should be configurable via the modules and theme props.
  • The editor should display the specified placeholder when empty.

Examples

Example 1:

Input:
<RichTextEditor
  value="Hello, world!"
  onChange={(content) => console.log(content)}
  modules={{ toolbar: [['bold', 'italic']] }}
  theme="snow"
  placeholder="Type something..."
/>
Output:
A Quill.js editor displaying "Hello, world!" with a bold and italic toolbar, using the 'snow' theme, and a placeholder "Type something..." when empty.
Explanation: The component initializes Quill.js with the provided value, modules, and theme. The onChange callback is called with "Hello, world!" initially.

Example 2:

Input:
<RichTextEditor
  value=""
  onChange={(content) => console.log(content)}
  placeholder="Start typing..."
/>
Output:
A Quill.js editor displaying the placeholder "Start typing..." because the value is empty.
Explanation: The component initializes Quill.js and displays the placeholder as the value is empty.

Example 3: (Error Handling)

Input:
<RichTextEditor
  value="Some content"
  onChange={(content) => console.log(content)}
  modules={{ toolbar: ['invalid-option'] }} // Invalid toolbar option
/>
Output:
A Quill.js editor displaying "Some content" and logging an error to the console (or displaying an error message in the UI) due to the invalid toolbar option. The editor should still function, ignoring the invalid option.
Explanation: The component should attempt to initialize Quill.js, but gracefully handle the error caused by the invalid toolbar option, preventing the application from crashing.

Constraints

  • The component must be written in TypeScript.
  • You can choose any suitable rich text editor library (Quill.js is recommended). Clearly state your choice in your solution.
  • The component should be reasonably performant, avoiding unnecessary re-renders.
  • The value prop should be a string.
  • The modules prop should be an object conforming to the Quill.js module structure (or the equivalent for your chosen library).
  • The theme prop should be a string representing a valid theme name for the chosen editor.

Notes

  • Consider using React's useEffect hook to manage the editor's lifecycle (initialization and destruction).
  • Think about how to efficiently update the editor's content when the value prop changes. Avoid unnecessary re-renders.
  • Pay attention to error handling and provide informative error messages if something goes wrong.
  • Focus on creating a clean and reusable component with a well-defined API.
  • If using Quill.js, refer to the official documentation for details on modules and themes: https://quilljs.com/docs/modules/ and https://quilljs.com/docs/themes/
Loading editor...
typescript