https://github.com/klarna/remote-frames
Render a subset of the React tree to a different location, from many locations, without having to coordinate them
https://github.com/klarna/remote-frames
iframe in-k portals react react-dom
Last synced: 7 months ago
JSON representation
Render a subset of the React tree to a different location, from many locations, without having to coordinate them
- Host: GitHub
- URL: https://github.com/klarna/remote-frames
- Owner: klarna
- License: apache-2.0
- Created: 2017-10-02T11:41:09.000Z (over 8 years ago)
- Default Branch: master
- Last Pushed: 2023-02-28T01:51:32.000Z (almost 3 years ago)
- Last Synced: 2025-06-09T17:16:12.212Z (7 months ago)
- Topics: iframe, in-k, portals, react, react-dom
- Language: JavaScript
- Homepage:
- Size: 894 KB
- Stars: 27
- Watchers: 282
- Forks: 12
- Open Issues: 13
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Deprecated
No longer being maintained.
# @klarna/remote-frames
[](https://travis-ci.org/klarna/remote-frames)
[](https://www.npmjs.com/package/@klarna/remote-frames)
Render a subset of the React tree to a different location, from many locations, without having to coordinate them.
## Usage
Say that you have an HTML with two DOM nodes that you want to render to:
```html
Remote frame
```
…and for some reason, you want elements in the React tree rendered under the `"main-content-node"` to be able to inject elements into the `"dialogs-node"`. The `RemoteFrame` allows you to send this elements to the remote tree (the one under `"dialogs-node"`).
```js
import React, { Component } from 'react'
import { render } from 'react-dom'
import { RemoteFrame, RemoteFramesProvider } from '@klarna/remote-frames'
const Dialog1 = () =>
Lorem ipsum
const Dialog2 = () =>
Dolor sit amet
class App extends Component {
constructor() {
super()
this.state = {
showDialog1: false,
showDialog2: false,
}
}
render() {
const { showDialog1, showDialog2 } = this.state
return {
console.log(
'a new frame was added to the dialogs-node stack',
frameJSX
)
}}
onFrameRemoved={frameJSX => {
console.log(
'a frame was removed from the dialogs-node stack',
frameJSX
)
}}
onNoFrames={lastJSXRemoved => {
console.log(
'all frames have been removed from the stack',
lastJSXRemoved
)
}}>
App that demonstrates remote-frames
this.setState({
showDialog1: !showDialog1
})}>
{showDialog1 ? 'Hide Dialog 1' : 'Show Dialog 1'}
this.setState({
showDialog2: !showDialog1
})}>
{showDialog2 ? 'Hide Dialog 2' : 'Show Dialog 2'}
{showDialog1 &&
}
{showDialog2 &&
}
}
}
render(
,
document.getElementById('main-content-node')
)
```
Whenever you click the "Show" / "Hide" buttons, the dialogs are sent to a React tree under the `"dialogs-node"`, and rendered one at a time. If there was no dialog being shown at the time, then the new dialog is added; if there was a dialog shown already, the new dialog is shown instead, but then if the new dialog is removed, the old dialog is shown again, as in a sort of stack.
State of the elements inside the `RemoteFrame` is preserved, even when unmounted.
### Missing RemoteFramesProvider
If there is no `RemoteFramesProvider` in the tree before the `RemoteFrame`, the content of `RemoteFrame` will just be rendered in place.
### Context
For the React.context to be propagated to the new tree, you have to manually specify what props of the context you want to propagate:
```js
import React, { Component } from 'react'
import { render } from 'react-dom'
import PropTypes from 'prop-types'
import { getContext, withContext } from 'recompose'
import {
RemoteFrame,
RemoteFramesProvider
} from '@klarna/remote-frames'
const Dialog1 = getContext({ content1: PropTypes.string })(({content1}) =>
{content1}
)
const Dialog2 = getContext({ content2: PropTypes.string })(({content2}) =>
{content2}
)
const App = withContext(
{
content1: PropTypes.string,
content2: PropTypes.string,
},
() => ({
content1: 'Hello Dialog 1',
content2: 'Hello Dialog 2',
})
)(() => {
return
App that demonstrates remote-frames
this.setState({
showDialog1: !showDialog1
})}>
{showDialog1 ? 'Hide Dialog 1' : 'Show Dialog 1'}
this.setState({
showDialog2: !showDialog1
})}>
{showDialog2 ? 'Hide Dialog 2' : 'Show Dialog 2'}
})
render(
,
document.getElementById('main-content-node')
)
```
### Callbacks on `RemoteFramesProvider`
Two callbacks are available on `RemoteFramesProvider`:
- `onFrameAdded`: gets called whenever another frame is added to the stack
- `onNoFrames`: gets called whenever all frames are removed from the stack
- `onFrameRemoved`: gets called whenever a frame is removed from the stack
### Passing the `targetDomElement`
The `targetDomElement` used to render the new React tree can be passed directly to the `RemoteFramesProvider` as a prop, or it can be passed as a Promise, allowing you to wait until the targetDomElement is available (for example if it is rendered in another window).
Frames stacked before the `targetDomElement` is available will be queued, so you will not lose any information.
### Wrapping into `wrapperComponent`
The `wrapperComponent` (alongside with `wrapperComponentProps`) used to wrap `GlobalTarget` into HOC (for example if it is needed to wrap everything into `ThemeProvider`, etc.).
```js
```