or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.md

index.mddocs/

0

# React Portal

1

2

React Portal is a React library that simplifies working with React Portals by providing two main components: Portal and PortalWithState. The Portal component transports children into a new React Portal (typically appended to document.body) and supports targeting custom DOM elements, server-side rendering, and returning arrays without wrapper divs. The PortalWithState component adds convenience by managing its own state and providing features like close-on-ESC, close-on-outside-click, and callback functions for open/close events.

3

4

## Package Information

5

6

- **Package Name**: react-portal

7

- **Package Type**: npm

8

- **Language**: JavaScript (React)

9

- **Installation**: `npm install react-portal` or `yarn add react-portal`

10

11

## Core Imports

12

13

```javascript

14

import { Portal, PortalWithState } from 'react-portal';

15

```

16

17

For CommonJS:

18

19

```javascript

20

const { Portal, PortalWithState } = require('react-portal');

21

```

22

23

## Basic Usage

24

25

```jsx

26

import React from 'react';

27

import { Portal, PortalWithState } from 'react-portal';

28

29

// Basic Portal usage

30

const MyModal = ({ isOpen, children }) => (

31

isOpen && <Portal>{children}</Portal>

32

);

33

34

// PortalWithState usage with built-in controls

35

const AdvancedModal = () => (

36

<PortalWithState closeOnOutsideClick closeOnEsc>

37

{({ openPortal, closePortal, isOpen, portal }) => (

38

<React.Fragment>

39

<button onClick={openPortal}>Open Modal</button>

40

{portal(

41

<div style={{ background: 'white', padding: '20px' }}>

42

<h2>Modal Content</h2>

43

<button onClick={closePortal}>Close</button>

44

</div>

45

)}

46

</React.Fragment>

47

)}

48

</PortalWithState>

49

);

50

```

51

52

## Architecture

53

54

React Portal is built around React's Portal API with the following key components:

55

56

- **Portal Component**: Core portal functionality with automatic React version compatibility (16+ vs 15)

57

- **PortalWithState Component**: Stateful wrapper providing built-in open/close management

58

- **Compatibility Layer**: Automatic fallback between modern `ReactDOM.createPortal` and legacy `unstable_renderSubtreeIntoContainer`

59

- **Event Management**: Built-in ESC key and outside click handling for modals and popups

60

- **SSR Support**: Server-side rendering compatibility through DOM environment detection

61

62

## Capabilities

63

64

### Basic Portal Creation

65

66

Core portal component that transports React elements into a React Portal, breaking out of normal DOM hierarchy for proper styling and positioning.

67

68

```javascript { .api }

69

/**

70

* Portal component that renders children into a React Portal

71

*/

72

class Portal extends React.Component<PortalProps> {}

73

74

interface PortalProps {

75

/** React elements to be portaled */

76

children: React.ReactNode;

77

/** Optional target DOM element (defaults to auto-created div in document.body) */

78

node?: HTMLElement | Element | null;

79

}

80

```

81

82

**Usage Examples:**

83

84

```jsx

85

// Portal to document.body (default)

86

<Portal>

87

<div>This content appears at the end of document.body</div>

88

</Portal>

89

90

// Portal to custom element

91

const customTarget = document.getElementById('modal-root');

92

<Portal node={customTarget}>

93

<div>This content appears in the custom element</div>

94

</Portal>

95

96

// Conditional portal

97

{isModalOpen && (

98

<Portal>

99

<div className="modal-overlay">

100

<div className="modal-content">Modal content here</div>

101

</div>

102

</Portal>

103

)}

104

```

105

106

### Stateful Portal Management

107

108

Advanced portal component with built-in state management, event handling, and render prop pattern for complete portal control.

109

110

```javascript { .api }

111

/**

112

* Stateful portal component using render prop pattern

113

*/

114

class PortalWithState extends React.Component<PortalWithStateProps> {}

115

116

interface PortalWithStateProps {

117

/** Render prop function receiving portal controls */

118

children: (controls: PortalControls) => React.ReactNode;

119

/** Initial open state (default: false) */

120

defaultOpen?: boolean;

121

/** Target DOM element for portal */

122

node?: HTMLElement | Element | null;

123

/** Close portal when ESC key is pressed */

124

closeOnEsc?: boolean;

125

/** Close portal when clicking outside */

126

closeOnOutsideClick?: boolean;

127

/** Callback fired when portal opens (default: empty function) */

128

onOpen?: () => void;

129

/** Callback fired when portal closes (default: empty function) */

130

onClose?: () => void;

131

}

132

133

interface PortalControls {

134

/** Function to open the portal */

135

openPortal: (event?: React.SyntheticEvent) => void;

136

/** Function to close the portal */

137

closePortal: () => void;

138

/** Function that wraps content to be portaled */

139

portal: (children: React.ReactNode) => React.ReactNode;

140

/** Current open/closed state */

141

isOpen: boolean;

142

}

143

```

144

145

**Usage Examples:**

146

147

```jsx

148

// Basic modal with ESC and outside click handling

149

<PortalWithState closeOnOutsideClick closeOnEsc>

150

{({ openPortal, closePortal, isOpen, portal }) => (

151

<React.Fragment>

152

<button onClick={openPortal}>Open Modal</button>

153

{portal(

154

<div className="modal-backdrop">

155

<div className="modal">

156

<h2>Modal Title</h2>

157

<p>Modal content goes here</p>

158

<button onClick={closePortal}>Close</button>

159

</div>

160

</div>

161

)}

162

</React.Fragment>

163

)}

164

</PortalWithState>

165

166

// Modal with callbacks and custom target

167

<PortalWithState

168

closeOnEsc

169

onOpen={() => console.log('Modal opened')}

170

onClose={() => console.log('Modal closed')}

171

node={document.getElementById('overlay-root')}

172

>

173

{({ openPortal, closePortal, isOpen, portal }) => (

174

<div>

175

<button onClick={openPortal}>

176

{isOpen ? 'Close' : 'Open'} Lightbox

177

</button>

178

{portal(

179

<div className="lightbox">

180

<img src="/image.jpg" alt="Large image" />

181

<button onClick={closePortal}>×</button>

182

</div>

183

)}

184

</div>

185

)}

186

</PortalWithState>

187

188

// Loading overlay that starts open

189

<PortalWithState defaultOpen>

190

{({ closePortal, portal }) =>

191

portal(

192

<div className="loading-overlay">

193

<div className="spinner">Loading...</div>

194

<button onClick={closePortal}>Cancel</button>

195

</div>

196

)

197

}

198

</PortalWithState>

199

```

200

201

## React Version Compatibility

202

203

React Portal automatically handles React version compatibility:

204

205

- **React 16+**: Uses `ReactDOM.createPortal()` (modern approach)

206

- **React 15**: Falls back to `ReactDOM.unstable_renderSubtreeIntoContainer()` (legacy approach)

207

- **SSR**: Detects server environment and renders `null` safely

208

209

## Error Handling

210

211

React Portal handles cleanup automatically:

212

213

- DOM nodes created by Portal are removed on unmount

214

- Event listeners are properly cleaned up when PortalWithState unmounts

215

- No memory leaks or orphaned DOM elements

216

217

## Common Use Cases

218

219

- **Modals and Dialogs**: Break out of parent container z-index stacking

220

- **Tooltips and Popovers**: Position relative to viewport instead of parent

221

- **Loading Overlays**: Cover entire page regardless of component location

222

- **Notifications**: Render at consistent location in DOM tree

223

- **Lightboxes**: Full-screen overlays independent of component hierarchy