diff --git a/package.json b/package.json
index 29c170e..c17f7f2 100644
--- a/package.json
+++ b/package.json
@@ -24,6 +24,7 @@
"devDependencies": {
"babel-cli": "^6.26.0",
"babel-core": "^6.26.3",
+ "babel-eslint": "^10.0.3",
"babel-plugin-external-helpers": "^6.22.0",
"babel-plugin-transform-import-css": "^0.1.6",
"babel-plugin-transform-react-remove-prop-types": "^0.4.6",
@@ -32,7 +33,7 @@
"eslint": "^4.2.0",
"eslint-plugin-react": "^7.1.0",
"prop-types": "^15.6.1",
- "react": "^16.4.0",
+ "react": "^16.8.0",
"react-dom": "^16.4.0",
"rollup": "^0.60.7",
"rollup-plugin-babel": "^3.0.4",
diff --git a/src/NoPrint.jsx b/src/NoPrint.jsx
index a0ba0e2..1c425f9 100644
--- a/src/NoPrint.jsx
+++ b/src/NoPrint.jsx
@@ -7,11 +7,9 @@ const propTypes = {
children: PropTypes.node.isRequired,
};
-export default class NoPrint extends React.PureComponent {
- render() {
- const { children, force } = this.props;
- const force_ = force ? s._force : '';
- return
{children}
;
- }
+export default function NoPrint ({ children, force }) {
+ const force_ = force ? s._force : '';
+ return {children}
;
}
+
NoPrint.propTypes = propTypes;
diff --git a/src/Print.jsx b/src/Print.jsx
index 8fc8117..22f9abe 100644
--- a/src/Print.jsx
+++ b/src/Print.jsx
@@ -1,7 +1,6 @@
-import React from 'react';
+import React, { useState, useEffect, useRef } from 'react';
+import { usePrintProvider } from './PrintProviderContext';
import PropTypes from 'prop-types';
-
-import PrintProvider from './PrintProvider';
import { debug } from './common';
import s from './Print.css';
@@ -13,76 +12,61 @@ const propTypes = {
exclusive: PropTypes.bool,
printOnly: PropTypes.bool
};
-const contextTypes = PrintProvider.childContextTypes;
-
-export default class Print extends React.Component {
-
- constructor(props) {
- super(props);
- this.state = {
- printOffsetLeft: 0,
- printOffsetTop: 0
- };
- }
- componentDidMount() {
+export default function Print (props) {
+ const [printOffsetLeft, setPrintOffsetLeft] = useState(0);
+ const [printOffsetTop, setPrintOffsetTop] = useState(0);
+ const { regPrintable, unregPrintable } = usePrintProvider();
+ const printElement = useRef(null);
+ const main_ = (props.main || props.single) ? s._main : '';
+ const excl_ = (props.exclusive || props.printOnly) ? s._exclusive : '';
+ const isPrint = window.matchMedia('print').matches;
+ const offset_ = ((printOffsetTop || printOffsetLeft) && main_ && isPrint) ?
+ { marginTop: -printOffsetTop, marginLeft: -printOffsetLeft } : {};
+ const globalClassName = 'react-easy-print-print'; // using in hiddenAll
+ const className = `${globalClassName} ${s.root} ${main_} ${excl_}`;
- if (this.props.name) {
- debug('init printable', this.props.name);
- const isSingle = (this.props.main || this.props.single);
- this.context.printProvider && this.context.printProvider.regPrintable(this.props.name, , isSingle);
+ useEffect(() => {
+ if (props.name) {
+ debug('init printable', props.name);
+ const isSingle = (props.main || props.single);
+ regPrintable(name, , isSingle);
}
- if (this.props.main || this.props.single) {
+ if (props.main || props.single) {
window.matchMedia('print').onchange = () => {
const isPrint = window.matchMedia('print').matches;
if (isPrint) {
const bodyRect = document.body.getBoundingClientRect();
- const elem = this.printElement;
+ const elem = printElement.current;
const elemRect = elem && elem.getBoundingClientRect();
const printOffsetLeft = elemRect && (elemRect.left - bodyRect.left);
const printOffsetTop = elemRect && (elemRect.top - bodyRect.top);
- this.setState({
- printOffsetTop,
- printOffsetLeft,
- });
+ setPrintOffsetLeft(printOffsetLeft);
+ setPrintOffsetTop(printOffsetTop);
} else {
- this.setState({
- printOffsetTop: 0,
- printOffsetLeft: 0
- })
+ setPrintOffsetLeft(0);
+ setPrintOffsetTop(0);
}
};
}
- }
-
- componentWillUnmount() {
- if (this.props.name) {
- debug('remove printable', this.props.name);
- const isSingle = (this.props.main || this.props.single);
- this.context.printProvider && this.context.printProvider.unregPrintable(this.props.name, isSingle);
- }
- if (this.props.main || this.props.single) {
- window.matchMedia('print').onchange = null;
- }
- }
-
- render() {
-
- const { children, main, single, exclusive, printOnly } = this.props;
- const { printOffsetLeft, printOffsetTop } = this.state;
- const main_ = (main || single) ? s._main : '';
- const excl_ = (exclusive || printOnly) ? s._exclusive : '';
- const isPrint = window.matchMedia('print').matches;
- const offset_ = ((printOffsetTop || printOffsetLeft) && main_ && isPrint) ? { marginTop: -printOffsetTop, marginLeft: -printOffsetLeft } : {};
- const globalClassName = 'react-easy-print-print'; // using in hiddenAll
- const className = `${globalClassName} ${s.root} ${main_} ${excl_}`;
- return this.printElement = el} style={offset_} className={className}>{children}
;
- }
+ return () => {
+ if (props.name) {
+ debug('remove printable', props.name);
+ const isSingle = (props.main || props.single);
+ unregPrintable(props.name, isSingle);
+ }
+
+ if (props.main || props.single) {
+ window.matchMedia('print').onchange = null;
+ }
+ };
+ }, []);
+ return {props.children}
;
}
+
Print.propTypes = propTypes;
-Print.contextTypes = contextTypes;
diff --git a/src/PrintProvider.jsx b/src/PrintProvider.jsx
index 7fc68c5..3c8ebc8 100644
--- a/src/PrintProvider.jsx
+++ b/src/PrintProvider.jsx
@@ -1,125 +1,129 @@
-import React from 'react';
+import React, { useState, useEffect, useRef } from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
+import PrintProviderContext from './PrintProviderContext';
import s from './PrintProvider.css';
import { spliced, debug } from './common';
export const propTypes = {
loose: PropTypes.bool,
children: PropTypes.node.isRequired,
- invert: PropTypes.bool,
+ invert: PropTypes.bool
};
-export const childContextTypes = {
- printProvider: PropTypes.shape({
- regPrintable: PropTypes.func.isRequired,
- unregPrintable: PropTypes.func.isRequired,
- isPrint: PropTypes.bool.isRequired,
- }).isRequired,
+const ID = 'react-easy-print-render';
+
+const createRender = children => {
+ const el = document.createElement('div');
+ el.id = ID;
+ document.body.appendChild(el);
+ ReactDOM.render({children}
, el);
};
-export default class PrintProvider extends React.PureComponent {
- constructor(props) {
- super(props);
- this.state = {
- isInPrintPreview: false,
- printableNodes: [],
- };
- this.printableRegistry = {};
+const deleteRender = () => {
+ const el = document.getElementById(ID);
+ el && document.body.removeChild(el);
+};
+
+export default function PrintProvider (props) {
+
+ const [isInPrintPreview, setIsInPrintPreview] = useState(false);
+ const [printableNodes, setPrintableNodes ] = useState([]);
+
+ const printableRegistry = useRef({});
+ const hasSingle = useRef(false);
+
+ const loose = props.loose || props.invert;
+ const loose_ = loose ? s.loose : '';
+ const invert_ = props.invert ? s.invert : '';
+
+ useEffect(() => {
window.matchMedia('print').onchange = () => {
debug('toggle print mode', window.matchMedia('print').matches);
- this.setState({ isInPrintPreview: window.matchMedia('print').matches });
+ setIsInPrintPreview(window.matchMedia('print').matches);
};
+ }, []);
- this.hasSingle = false;
- }
+ useEffect(() => {
+ if (isInPrintPreview && printableNodes.length && !loose && !hasSingle.current) {
+ debug('render printable only', printableNodes);
+ const children = React.Children.map(printableNodes, (child, key) => {
+ return React.cloneElement(child, { key });
+ });
+ createRender({children}
);
+ }
+ setTimeout(() => deleteRender(), 0);
+ });
- getChildContext() {
- return {
- printProvider: {
- isPrint: window.matchMedia('print').matches,
- regPrintable: this.regPrintable.bind(this),
- unregPrintable: this.unregPrintable.bind(this),
- },
- };
- }
+ useEffect(() => {
+ debug('render everything', isInPrintPreview, printableNodes.length, !loose);
+ }, [isInPrintPreview, printableNodes.length, loose]);
// hideAll - is being used to cover all of React Portals, popups and modals and etc.
- hideAll() {
+ const hideAll = () => {
document.body.classList.add(s.hiddenAll);
- this.hasSingle = true;
- }
+ hasSingle.current = true;
+ };
- unhideAll() {
+ const unhideAll = () => {
document.body.classList.remove(s.hiddenAll);
- this.hasSingle = false;
- }
+ hasSingle.current = false;
+ };
- regPrintable(key, node) {
- const loose = this.props.loose || this.props.invert;
+ const regPrintable = (key, node) => {
+ const loose = props.loose || props.invert;
const isSingle = node.props.single || node.props.main;
- const { hasSingle } = this;
debug('reg printable', key, node);
- if (this.printableRegistry[key] !== undefined || loose) return;
- setTimeout(() => this.setState({
- printableNodes: this.state.printableNodes.concat(node),
- }), 0);
- this.printableRegistry[key] = this.state.printableNodes.length;
+ if (printableRegistry.current[key] !== undefined || loose) return;
+ setTimeout(
+ () =>
+ setPrintableNodes(printableNodes.concat(node)),
+ 0
+ );
+ printableRegistry.current[key] = printableNodes.length;
- if (isSingle && !hasSingle) {
- this.hideAll();
+ if (isSingle && !hasSingle.current) {
+ hideAll();
} else if (isSingle) {
- console.warn(new Error('react-easy-print warning \n\t you\'re using more than one `single` Print component'));
+ console.warn(
+ new Error(
+ 'react-easy-print warning \n\t you\'re using more than one `single` Print component'
+ )
+ );
}
- }
-
- unregPrintable(key, isSingle) {
- const loose = this.props.loose || this.props.invert;
- if (this.printableRegistry[key] === undefined || this.state.isInPrintPreview || loose) return;
- this.setState({
- printableNodes: spliced(this.state.printableNodes, this.printableRegistry[key]),
+ };
+
+ const unregPrintable = (key, isSingle) => {
+ const loose = props.loose || props.invert;
+ if (
+ printableRegistry.current[key] === undefined ||
+ isInPrintPreview ||
+ loose
+ )
+ return;
+ setPrintableNodes(
+ spliced(
+ printableNodes,
+ printableRegistry.current[key]
+ )
+ );
+ printableRegistry.current = Object.assign({}, printableRegistry.current, {
+ [key]: undefined
});
- this.printableRegistry = Object.assign({}, this.printableRegistry, { [key]: undefined });
if (isSingle) {
- this.unhideAll();
- }
- }
-
- createRender(children) {
- const el = document.createElement('div');
- el.id = 'render';
- document.body.appendChild(el);
-
- ReactDOM.render({children}
, el);
- }
-
- deleteRender() {
- const el = document.getElementById('render');
- el && document.body.removeChild(el);
- }
-
- render() {
- const { isInPrintPreview, printableNodes } = this.state;
- const loose = this.props.loose || this.props.invert;
- const { hasSingle } = this;
-
- if (isInPrintPreview && printableNodes.length && !loose && !hasSingle) {
- debug('render printable only', printableNodes);
- const children = React.Children.map(printableNodes, (child, key) => {
- return React.cloneElement(child, { key });
- });
-
- this.createRender({children}
);
+ unhideAll();
}
- setTimeout(() => this.deleteRender(), 0);
+ };
+
+ return (
+
+
+ {props.children}
+
+
+ );
+};
- debug('render everything', isInPrintPreview, printableNodes.length, !loose);
- const loose_ = loose ? s.loose : '';
- const invert_ = this.props.invert ? s.invert : '';
- return {this.props.children}
;
- }
-}
PrintProvider.propTypes = propTypes;
-PrintProvider.childContextTypes = childContextTypes;
diff --git a/src/PrintProviderContext.js b/src/PrintProviderContext.js
new file mode 100644
index 0000000..4e2d6b4
--- /dev/null
+++ b/src/PrintProviderContext.js
@@ -0,0 +1,15 @@
+
+import React, { useContext } from 'react';
+
+const PrintProviderContext = React.createContext();
+
+export const usePrintProvider = () => {
+ const { regPrintable, unregPrintable } = useContext(PrintProviderContext);
+
+ return {
+ regPrintable,
+ unregPrintable
+ };
+};
+
+export default PrintProviderContext;