Skip to content

Commit 0479959

Browse files
SavePointSamgaearon
authored andcommitted
Update Portals Documentation (#10840)
* Update Portals Documentation Correct some grammar to be more explicit and clear. Update example CodePen to better match code found in documentation. Update code example styles to match other code examples (ie. 'State and Lifecycle', 'Handling Events'). * Clean up comment to be accurate to example There was a small comment overlooked when reviewing the documentation. This fixes it to be accurate to the example as well as grammatically correct. * Update portals.md * More fixes
1 parent ba1396f commit 0479959

File tree

1 file changed

+41
-17
lines changed

1 file changed

+41
-17
lines changed

docs/docs/portals.md

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -44,47 +44,71 @@ A typical use case for portals is when a parent component has an `overflow: hidd
4444

4545
> Note:
4646
>
47-
> For most uses portals, you'll need to make sure to follow the proper accessibility guidelines.
47+
> It is important to remember, when working with portals, you'll need to make sure to follow the proper accessibility guidelines.
4848
4949
[Try out an example on CodePen.](https://codepen.io/acdlite/pen/JrKgmz)
5050

5151
## Portals and event bubbling
5252

53-
A nice feature of portals is that, even though the DOM node can be anywhere in the DOM tree, it behaves like a normal React child in every other way. Features like context work exactly the same regardless of whether the child is a portal.
53+
Even though a portal can be anywhere in the DOM tree, it behaves like a normal React child in every other way. Features like context work exactly the same regardless of whether the child is a portal, as the portal still exists in the *React tree* regardless of position in the *DOM tree*.
5454

55-
This includes event bubbling: an event fired from inside a portal will propagate to ancestors in the containing *React tree*, even if those elements are not ancestors in the *DOM tree*:
55+
This includes event bubbling. An event fired from inside a portal will propagate to ancestors in the containing *React tree*, even if those elements are not ancestors in the *DOM tree*. Assuming the following HTML structure:
56+
57+
```html
58+
<html>
59+
<body>
60+
<div id="app-root"></div>
61+
<div id="modal-root"></div>
62+
</body>
63+
</html>
64+
```
65+
66+
A Parent component in `#app-root` would be able to catch an uncaught, bubbling event from the sibling node #modal-root.
5667

5768
```js
58-
// These two containers are siblings in the DOM
59-
const appContainer = document.getElementById('app-container');
60-
const modalContainer = document.getElementById('modal-container');
69+
const appRoot = document.getElementById('app-root');
70+
const modalRoot = document.getElementById('modal-root');
6171

6272
class Parent extends React.Component {
63-
state = {clicks: 0};
64-
onClick = () => {
65-
// This will fire when the button in Child is clicked, even though
66-
// button is not direct descendant in the DOM.
67-
this.setState(state => ({clicks: state.clicks + 1}));
68-
};
73+
constructor(props) {
74+
super(props);
75+
this.state = {clicks: 0};
76+
this.handleClick = this.handleClick.bind(this);
77+
}
78+
79+
handleClick() {
80+
// This will fire when the button in Child is clicked, updating Parent's state,
81+
// even though Child is not a direct descendant in the DOM.
82+
this.setState(prevState => ({
83+
clicks: prevState.clicks + 1
84+
}));
85+
}
86+
6987
render() {
7088
return (
7189
<div onClick={this.onClick}>
7290
<p>Number of clicks: {this.state.clicks}</p>
7391
<p>Open up the browser DevTools to observe that the button is not a child the div with onClick handler.</p>
74-
{ReactDOM.createPortal(<Child />, modalContainer)}
92+
{ReactDOM.createPortal(<Child />, modalRoot)}
7593
</div>
7694
);
7795
}
7896
}
7997

8098
function Child() {
81-
return <button>Click</button>;
99+
// The click event on this button will bubble up to parent,
100+
// because there is no 'onClick' attribute defined
101+
return (
102+
<div className="modal">
103+
<button>Click</button>
104+
</div>
105+
);
82106
}
83107

84108

85-
ReactDOM.render(<Parent />, appContainer);
109+
ReactDOM.render(<Parent />, appRoot);
86110
```
87111

88-
[Try this example on CodePen](https://codepen.io/acdlite/pen/MEJEVV).
112+
[Try this example on CodePen](https://codepen.io/gaearon/pen/jGBWpE).
89113

90-
The advantage of treating portal event bubbling this way is that it makes it easier to build abstractions. For example, if you render a `<Modal />` component, the parent can capture its events regardless of whether it's implemented using portals.
114+
Catching an event bubbling up from a portal in a parent component allows the development of more flexible abstractions that are not inherently reliant on portals. For example, if you render a `<Modal />` component, the parent can capture its events regardless of whether it's implemented using portals.

0 commit comments

Comments
 (0)