or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

tessl/npm-react-portal

React library that simplifies working with React Portals by providing Portal and PortalWithState components for breaking out of normal DOM hierarchy.

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/react-portal@4.3.x

To install, run

npx @tessl/cli install tessl/npm-react-portal@4.3.0

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