1.0.0 • Published 6 years ago

react-external-window v1.0.0

Weekly downloads
11
License
MIT
Repository
github
Last release
6 years ago

React External Window

With React External Window you can render React components in an external child window from within an app.

Works with redux-connected components!

Installation

Requires React v16 and assumes you’re using npm package manager with a module bundler like Webpack or Browserify to consume CommonJS modules.

npm i --save react-external-window

Usage

A Window component accepts the following props. For more information, visit MDN's documentation on window.open.

Prop NameDescriptionDefault
urlDo not provide one if you want to render the children provided to WindowEmpty String
titleTitle to display in title bar'Untitled'
nameName passed to window.open
yMaps to top property of windowFeatures0
xMaps to left poperty of windowFeatures0
resourcesArray of resources to include in external window (see Resources Example)
widthInitial width in pixels of child window
heightInitial height in pixels of child window
menubarShow menubar on child window. Acceptable values are 1/0, yes/no0
scrollbarsShow scrollbars on child window. Acceptable values are 1/0, yes/no1
statusShow status bar on child window. Acceptable values are 1/0, yes/no0
toolbarShow toolbar on child window. Acceptable values are 1/0, yes/no0
titlebarShow menubar on child window. Acceptable values are 1/0, yes/no0
onLoadPassed reference to newly created window
onClosePassed reference to closing window, useful for saving properties like position or size
onBlockCalling window.open fails, usually due to a popup blocker

Parts of a Child Window

React External Window can have be supplied children or a function, which is passed the external window instance.

<Window 
    url=''
    title='My Window'
>
    //...children
</Window>

Using this.props.children as a render prop:

<Window 
    url=''
    title='My Window'
>
{(window) => (
    // ...children to render
    <button onClick={() => window.close()}>Close!</button>
)}
</Window>

Having access to the external window instance allows methods to be called on the external window instead of the parent window. In the example above calling window.close() without access to the instance would call close on the parent window, which is not allowed so nothing would happen.

Example

You have an app that has some data visualizations, among them a component called SweetChart. You want users to see and interact with this SweetChart while also carrying out other tasks. With React External Window the SweetChart (probably a redux-connected component) can live in an external window without the need to load your entire site (or any site) into it.

import React, { Component } from 'react';
import { connect } from 'react-redux';
import Window from 'react-external-window';
import { actionTypes } from './reducer';
import SweetChart from './SweetChart';


class App extends Component {
    onOpenBtnClick = () => {
        this.props.onOpenBtnClick();
    }

    render() {
        return (
            <div>
                <SweetChart />
                <button onClick={this.onOpenBtnClick}>Open!</button>
                <div>{this.props.message}</div>
                {this.props.openWindow &&
                    <Window 
                        url=''
                        title='My Window'
                        name='child'
                        onClose={this.props.onCloseWindow}
                    >
                    {(window) => (
                        <React.Fragment>
                            <SweetChart />
                            <button onClick={() => window.close()}>Close!</button>
                        </React.Fragment>
                    )}
                    </Window>
                }
            </div>
        );
    } 
}

const mapStateToProps = (state) => ({
    openWindow: state.openWindow,
    message: state.message,
});

const mapDispatchToProps = (dispatch) => ({
    onOpenBtnClick: () => dispatch({ type: actionTypes.OPEN_WINDOW }),
    onCloseWindow: (window) => dispatch({ type: actionTypes.CLOSE_WINDOW, payload: window }), // save some info about the window instance to use when opening next time
});

export default connect(mapStateToProps, mapDispatchToProps)(App);

Resources Example

If the external window you create uses about:blank, in other words, doesn't load in an actual website, you'll most likely need to supply it with the resources needed for styling and functionality.

The example below shows how to use the resources prop. resources accepts an array of resources, each resource can be of the following format:

Resource TypeFormat
1Node or NodeList[selector, 'append'|'prepend', 'head'|'body']
2Absolute URL with extensionString
3Absolute URL without extension[url, 'js'|'css']

Migrating from v0.2.0 to v1.x.x Prior to v1.0.0, parent styles would be copied automatically if stylesheet was not provided a URL. That behavior has been removed in favor of the more flexible resources prop. To achieve the same effect, add the following to your resources array:

[document.querySelectorAll('style'), 'append', 'head'],

<Window
    url=""
    title="My Window"
    resources={[
        [document.querySelectorAll('style'), 'append', 'head'], // 1
        [document.querySelector('svg'), 'prepend', 'body'], // 1
        'https://kerryrusso.com/blog/wp-content/themes/grateful/css/reset.css?ver=4.9.6', // 2
        'https://kerryrusso.com/blog/wp-content/themes/grateful/style.css?ver=4.9.6', // 2
        'https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css', // 2
        [
        'https://kerryrusso.com/blog/wp-content/themes/grateful/style',
        'css',
        ], // 3
        ['https://unpkg.com/jquery', 'js'], // 3
    ]}
    >
    {window => (
        <React.Fragment>
        <Form />
        <button
            className="btn btn-danger"
            onClick={() => {
            window.close();
            }}
        >
            Close!
        </button>
        </React.Fragment>
    )}
</Window>