Skip to content

Commit 0597299

Browse files
committed
Clarify & expand README intro
1 parent 6020a9b commit 0597299

File tree

1 file changed

+19
-12
lines changed

1 file changed

+19
-12
lines changed

README.md

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@
66

77
**Build an element once, move it anywhere**
88

9-
Added in React 16.0, React's built-in [portals](https://reactjs.org/docs/portals.html) let you render an element in a meaningful location within the React tree, but then place the output into a DOM node elsewhere.
9+
Added in React 16.0, React's built-in [portals](https://reactjs.org/docs/portals.html) let you render an element in a meaningful location within your React component hierarchy, but then send the output to a DOM node elsewhere.
1010

11-
Reverse portals let you do the opposite: pull a rendered element from elsewhere into a meaningful location within your React tree. This allows you to reparent DOM nodes, so you can move React-rendered elements around your React tree and the DOM without re-rendering them. Reverse portals also allow you to pull a rendered node out of the tree entirely, and return it later, all without rerendering the node.
11+
Reverse portals let you do the opposite: _pull_ a rendered element from elsewhere into a target location within your React tree. This allows you to reparent DOM nodes, so you can move React-rendered elements around your React tree and the DOM without re-rendering them.
12+
13+
Reverse portals also allow you to take a React-rendered node out of the DOM entirely, and return it later, all without rerendering the node.
1214

1315
(In a rush? Check out [the examples](https://httptoolkit.github.io/react-reverse-portal/))
1416

@@ -19,12 +21,13 @@ This is useful in a few cases:
1921
* Your elements are expensive to render, and you'd like to render them once and then place/unplace them later (e.g. a reusable pool of expensive-to-render elements that can be shared among different parts of your application).
2022
* You want to define the contents of an element separately from where it actually appears in the tree, e.g. modals, breadcrumbs, etc (possible with normal portals, but made more flexible & declarative with reverse portals)
2123

22-
In [HTTP Toolkit](https://httptoolkit.tech) for example, this is used to render [Monaco Editor](https://github.com/microsoft/monaco-editor) (an expensive-to-initialize rich text editor) only once, and then quickly & easily reuse the same editor to show the body of many different HTTP requests & responses in different places, without having to rebuild the component, making the UI much more responsive. Check out the full diff to implement that here: [httptoolkit-ui@8456eeca7a886b2d57b2a84bb4ecf299e20c77f8](https://github.com/httptoolkit/httptoolkit-ui/commit/8456eeca7a886b2d57b2a84bb4ecf299e20c77f8).
24+
In [HTTP Toolkit](https://httptoolkit.tech) for example, this is used to render [Monaco Editor](https://github.com/microsoft/monaco-editor) (an expensive-to-initialize rich text editor) only once, and then quickly & easily reuse the same editor to show the body of many different HTTP requests & responses in different places, without ever having to rebuild the component, making the UI much more responsive. Check out the full diff to implement that here: [httptoolkit-ui@8456eeca7a886b2d57b2a84bb4ecf299e20c77f8](https://github.com/httptoolkit/httptoolkit-ui/commit/8456eeca7a886b2d57b2a84bb4ecf299e20c77f8).
2325

2426
## Features
2527

2628
* Reparent rendered React elements without rerendering
2729
* Provide props at either the creation (in-portal) or usage (out-portal) locations, or both
30+
* Supports reparenting of both HTML and SVG elements
2831
* Single tiny file (2.5kB unminified, ungzipped) with zero dependencies
2932
* Works with React 16+
3033
* Written in TypeScript
@@ -43,31 +46,35 @@ Create a portal node, populate it with `InPortal`, and use it somewhere with `Ou
4346
import * as portals from 'react-reverse-portal';
4447

4548
const MyComponent = (props) => {
49+
// Create a portal node: this holds your rendered content
4650
const portalNode = React.useMemo(() => portals.createHtmlPortalNode(), []);
4751

4852
return <div>
4953
{/*
50-
Create the content that you want to move around.
51-
InPortals render as normal, but to detached DOM.
52-
Until this is used MyExpensiveComponent will not
53-
appear anywhere in the page.
54+
Render the content that you want to move around later.
55+
InPortals render as normal, but send the output to detached DOM.
56+
MyExpensiveComponent will be rendered immediately, but until
57+
portalNode is used in an OutPortal, MyExpensiveComponent, it
58+
will not appear anywhere on the page.
5459
*/}
5560
<portals.InPortal node={portalNode}>
5661
<MyExpensiveComponent
57-
// Optionally provide props to use before this enters the DOM
62+
// Optionally set props to use now, before this enters the DOM
5863
myProp={"defaultValue"}
5964
/>
6065
</portals.InPortal>
6166

6267
{/* ... The rest of your UI ... */}
6368

64-
{/* Pass the node to whoever might want to show it: */}
69+
{/* Later, pass the portal node around to whoever might want to use it: */}
6570
{ props.componentToShow === 'component-a'
6671
? <ComponentA portalNode={portalNode} />
6772
: <ComponentB portalNode={portalNode} /> }
6873
</div>;
6974
}
7075

76+
// Later still, pull content from the portal node and show it somewhere:
77+
7178
const ComponentA = (props) => {
7279
return <div>
7380
{/* ... Some more UI ... */}
@@ -86,9 +93,9 @@ const ComponentB = (props) => {
8693
myProp={"newValue"} // Optionally, override default values
8794
myOtherProp={123} // Or add new props
8895

89-
// These props go back to the InPortal, and trigger a component
90-
// render (but on the same component instance) as if they had
91-
// been passed directly.
96+
// These props go back to the content of the InPortal, and trigger a
97+
// component render (but on the same component instance) as if they
98+
// had been passed to MyExpensiveComponent directly.
9299
/>
93100
</div>;
94101
}

0 commit comments

Comments
 (0)