Reactive Interruption System in React
This challenge focuses on building a reusable interruption system within a React application. Imagine you're developing a complex UI where certain actions need to be interrupted based on specific conditions (e.g., stopping a drag-and-drop operation when a modal opens, or halting a form submission when validation fails). This system will provide a clean and predictable way to manage these interruptions.
Problem Description
You are tasked with creating a React hook, useInterruption, that allows components to register interruption handlers and trigger them when an interruption occurs. The hook should manage a list of registered handlers and provide a mechanism to interrupt them.
What needs to be achieved:
- Create a
useInterruptionhook that accepts aninterruptfunction as an argument. Thisinterruptfunction will be called to signal an interruption. - The hook should allow components to register interruption handlers using a
registerHandlerfunction returned by the hook. - Each registered handler should accept a callback function as an argument. This callback function will be executed when an interruption is triggered.
- The hook should also provide a
deregisterHandlerfunction to remove previously registered handlers. - The hook should ensure that all registered handlers are executed sequentially when an interruption is triggered.
Key Requirements:
- The
useInterruptionhook must be implemented using React'suseStateanduseEffecthooks. - The
registerHandlerfunction should return a unique identifier for the registered handler. This identifier is needed for deregistration. - The
interruptfunction should trigger the execution of all registered handlers. - The
deregisterHandlerfunction should remove the handler associated with the provided identifier. - The handlers should be executed in the order they were registered.
Expected Behavior:
When interrupt() is called:
- Each registered handler's callback function should be executed.
- The execution of handlers should be sequential (one handler completes before the next starts).
- Deregistering a handler should prevent it from being executed in subsequent interruptions.
Edge Cases to Consider:
- Calling
interrupt()with no registered handlers should not cause any errors. - Calling
deregisterHandler()with an invalid identifier should be handled gracefully (e.g., by doing nothing). - Handlers can be registered and deregistered multiple times.
- Consider how to handle errors within a handler's callback function. Should errors stop the execution of subsequent handlers? (For this challenge, assume errors should not stop execution).
Examples
Example 1:
Input:
Component A registers handler 1 with callback function 'handlerA'.
Component B registers handler 2 with callback function 'handlerB'.
interrupt() is called.
Output:
handlerA() is executed.
handlerB() is executed.
Explanation:
The interrupt function triggers the execution of all registered handlers in the order they were registered.
Example 2:
Input:
Component A registers handler 1 with callback function 'handlerA'.
interrupt() is called.
Component A deregisters handler 1.
interrupt() is called again.
Output:
First interrupt: handlerA() is executed.
Second interrupt: No handlers are executed.
Explanation:
Deregistration prevents the handler from being executed in subsequent interruptions.
Example 3: (Edge Case)
Input:
interrupt() is called with no registered handlers.
Output:
No handlers are executed.
Explanation:
Calling interrupt with no registered handlers should not cause an error.
Constraints
- The solution must be written in TypeScript.
- The
useInterruptionhook should be reusable across different components. - The execution of handlers should be synchronous. Asynchronous operations within handlers are allowed, but the handlers themselves should execute sequentially.
- The number of registered handlers should not exceed 100. (This is a practical limit to avoid performance issues in extreme cases).
Notes
- Think about how to manage the state of registered handlers effectively.
- Consider using a functional approach to handle the interruption logic.
- The
interruptfunction should be exposed to components that need to trigger interruptions. - Focus on creating a clean and well-documented API for the
useInterruptionhook. The hook should be easy to understand and use. - Error handling within the handlers is not a primary focus of this challenge, but consider how it might be handled in a real-world application.