React Portal System Implementation
This challenge asks you to implement a basic portal system in React using TypeScript. Portals allow you to render a React component's children in a DOM node that exists outside of the parent component's DOM hierarchy. This is useful for modals, tooltips, and other UI elements that should appear on top of other content, regardless of the parent's styling or layout.
Problem Description
You need to create a reusable Portal component that accepts a child React node and renders it within a specified DOM element. The Portal component should:
- Accept a
childrenprop: This prop will contain the React node(s) to be rendered within the portal. - Accept a
containerprop: This prop should be a reference to a DOM element where the portal's content will be rendered. If no container is provided, the portal should render its children to thedocument.body. - Handle unmounting correctly: When the
Portalcomponent unmounts, it should remove the portal's content from the DOM to prevent memory leaks. - Support TypeScript: The component should be written in TypeScript with appropriate type definitions for props and state.
Expected Behavior:
The Portal component should render its children within the provided container element. If no container is provided, it should render them to the document.body. The styling and layout of the parent component should not affect the appearance of the portal's content. Upon unmounting, the portal's content should be removed from the DOM.
Edge Cases to Consider:
- What happens if the
containerprop is null or undefined? - What happens if the
containerelement is removed from the DOM while the portal is mounted? - How to handle potential errors during the rendering process?
Examples
Example 1:
Input: <Portal><p>This is a portal!</p></Portal>
Output: A paragraph element containing "This is a portal!" rendered directly within the document body.
Explanation: No container is provided, so the content is rendered to the document body.
Example 2:
Input: <div id="portal-root"></div>
<Portal container={document.getElementById('portal-root')}>
<button>Click Me</button>
</Portal>
Output: A button element containing "Click Me" rendered within the div with the id "portal-root".
Explanation: The container is explicitly provided, so the content is rendered within that element.
Example 3: (Edge Case)
Input: <div id="portal-root"></div>
<Portal container={null}>
<button>Click Me</button>
</Portal>
Output: A button element containing "Click Me" rendered directly within the document body.
Explanation: The container is null, so the content is rendered to the document body.
Constraints
- The solution must be written in TypeScript.
- The
Portalcomponent should be a functional component. - The solution should be relatively concise and easy to understand.
- The solution should not rely on any external libraries beyond React and ReactDOM.
- The component should be reusable and adaptable to different scenarios.
Notes
- Consider using
ReactDOM.createPortalfor the core portal rendering functionality. - Think about how to handle the lifecycle of the portal and ensure proper cleanup when the component unmounts.
- Error handling is not a primary focus, but consider how you might gracefully handle cases where the container element is not found.
- Focus on the core functionality of rendering children within a specified container or the document body. Styling and advanced features are not required for this challenge.