React Undo/Redo System
Building an undo/redo system is a common requirement in many applications, allowing users to revert to previous states and reapply actions. This challenge asks you to implement a basic undo/redo functionality within a React component, demonstrating state management and event handling. This is a valuable skill for creating user-friendly and robust applications.
Problem Description
You are tasked with creating a React component that allows a user to input text into a text area and then undo and redo their changes. The component should maintain a history of the text area's content, enabling the user to step back and forward through their editing history.
What needs to be achieved:
- A React component with a text area for user input.
- "Undo" and "Redo" buttons.
- A history of text area content stored internally.
- Functionality to revert to previous states when "Undo" is clicked.
- Functionality to reapply undone changes when "Redo" is clicked.
- The component should update the text area content based on user input and undo/redo actions.
Key Requirements:
- The component must be written in TypeScript.
- The history should be stored as an array of strings, representing the text area's content at different points in time.
- The undo/redo functionality should be implemented using React state.
- The component should handle edge cases such as attempting to undo when there's no history or attempting to redo when there's no redo history.
Expected Behavior:
- When the user types in the text area, the current content is added to the history.
- Clicking "Undo" reverts the text area to the previous state in the history.
- Clicking "Redo" reapplies the undone change, moving the text area forward in the history.
- If "Undo" is clicked repeatedly, the text area should revert to earlier states.
- If "Redo" is clicked after undoing, the text area should move forward again.
- If "Undo" is clicked when the history is empty (only the initial state exists), nothing should happen.
- If "Redo" is clicked when there's no redo history, nothing should happen.
Edge Cases to Consider:
- Initial state of the text area.
- Empty input.
- Multiple consecutive undo/redo operations.
- Attempting to undo/redo beyond the bounds of the history.
- Performance with a very large history (though this is a simplified challenge, consider how your approach might scale).
Examples
Example 1:
Input: User types "Hello" into the text area, then " World".
Output: The text area displays "Hello World". The history is ["", "Hello", "Hello World"].
Explanation: The initial state is added to the history, followed by the content after each input.
Example 2:
Input: User types "Hello World", then clicks "Undo" once.
Output: The text area displays "Hello". The history is ["", "Hello", "Hello World"]. The current state is "Hello".
Explanation: The last change ("Hello World") is removed from the text area and the current state is set to "Hello".
Example 3:
Input: User types "Hello", then " World", then clicks "Undo" twice, then clicks "Redo" once.
Output: The text area displays "Hello". The history is ["", "Hello", "Hello World"].
Explanation: Undo twice reverts to the initial state. Redo once reapplies the first change ("Hello").
Constraints
- The history array should not exceed a length of 100. When a new change is added and the history exceeds this length, the oldest entry should be removed.
- The text area content should be a string.
- The component should render within a reasonable time (e.g., under 100ms). While not a primary focus, avoid unnecessary re-renders.
Notes
- Consider using React's
useStatehook to manage the text area content and the history. - Think about how to efficiently update the history and the current state.
- You don't need to worry about saving the history to local storage or any persistent storage. The history is purely in-memory.
- Focus on the core undo/redo logic and the interaction with the text area. Styling is not required.
- A functional component is preferred.