UNPKG

3.43 kBJavaScriptView Raw
1import React, { PureComponent } from 'react';
2
3function _defineProperty(obj, key, value) {
4 if (key in obj) {
5 Object.defineProperty(obj, key, {
6 value: value,
7 enumerable: true,
8 configurable: true,
9 writable: true
10 });
11 } else {
12 obj[key] = value;
13 }
14
15 return obj;
16}
17
18function _inheritsLoose(subClass, superClass) {
19 subClass.prototype = Object.create(superClass.prototype);
20 subClass.prototype.constructor = subClass;
21 subClass.__proto__ = superClass;
22}
23
24var canUseDOM = !!(typeof window !== 'undefined' && window.document && window.document.createElement);
25function withSideEffect(reducePropsToState, handleStateChangeOnClient, mapStateOnServer) {
26 if (typeof reducePropsToState !== 'function') {
27 throw new Error('Expected reducePropsToState to be a function.');
28 }
29
30 if (typeof handleStateChangeOnClient !== 'function') {
31 throw new Error('Expected handleStateChangeOnClient to be a function.');
32 }
33
34 if (typeof mapStateOnServer !== 'undefined' && typeof mapStateOnServer !== 'function') {
35 throw new Error('Expected mapStateOnServer to either be undefined or a function.');
36 }
37
38 function getDisplayName(WrappedComponent) {
39 return WrappedComponent.displayName || WrappedComponent.name || 'Component';
40 }
41
42 return function wrap(WrappedComponent) {
43 if (typeof WrappedComponent !== 'function') {
44 throw new Error('Expected WrappedComponent to be a React component.');
45 }
46
47 var mountedInstances = [];
48 var state;
49
50 function emitChange() {
51 state = reducePropsToState(mountedInstances.map(function (instance) {
52 return instance.props;
53 }));
54
55 if (SideEffect.canUseDOM) {
56 handleStateChangeOnClient(state);
57 } else if (mapStateOnServer) {
58 state = mapStateOnServer(state);
59 }
60 }
61
62 var SideEffect =
63 /*#__PURE__*/
64 function (_PureComponent) {
65 _inheritsLoose(SideEffect, _PureComponent);
66
67 function SideEffect() {
68 return _PureComponent.apply(this, arguments) || this;
69 }
70
71 // Try to use displayName of wrapped component
72 // Expose canUseDOM so tests can monkeypatch it
73 SideEffect.peek = function peek() {
74 return state;
75 };
76
77 SideEffect.rewind = function rewind() {
78 if (SideEffect.canUseDOM) {
79 throw new Error('You may only call rewind() on the server. Call peek() to read the current state.');
80 }
81
82 var recordedState = state;
83 state = undefined;
84 mountedInstances = [];
85 return recordedState;
86 };
87
88 var _proto = SideEffect.prototype;
89
90 _proto.UNSAFE_componentWillMount = function UNSAFE_componentWillMount() {
91 mountedInstances.push(this);
92 emitChange();
93 };
94
95 _proto.componentDidUpdate = function componentDidUpdate() {
96 emitChange();
97 };
98
99 _proto.componentWillUnmount = function componentWillUnmount() {
100 var index = mountedInstances.indexOf(this);
101 mountedInstances.splice(index, 1);
102 emitChange();
103 };
104
105 _proto.render = function render() {
106 return React.createElement(WrappedComponent, this.props);
107 };
108
109 return SideEffect;
110 }(PureComponent);
111
112 _defineProperty(SideEffect, "displayName", "SideEffect(" + getDisplayName(WrappedComponent) + ")");
113
114 _defineProperty(SideEffect, "canUseDOM", canUseDOM);
115
116 return SideEffect;
117 };
118}
119
120export default withSideEffect;