Skip to content

Commit 3a9686d

Browse files
committed
Support React 16
1 parent 402016e commit 3a9686d

File tree

3 files changed

+86
-32
lines changed

3 files changed

+86
-32
lines changed

package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,15 @@
4343
},
4444
"devDependencies": {
4545
"async": "~1.5.0",
46+
"core-js": "^2.5.1",
4647
"expect.js": "0.3.x",
4748
"jquery": "~1.11.3",
4849
"object-assign": "~4.0.1",
4950
"pre-commit": "1.x",
50-
"rc-tools": "6.x",
5151
"rc-test": "6.x",
52-
"react": "15.x",
53-
"react-dom": "15.x"
52+
"rc-tools": "6.x",
53+
"react": "^16.0.0-rc.3",
54+
"react-dom": "^16.0.0-rc.3"
5455
},
5556
"pre-commit": [
5657
"lint"

src/index.js

Lines changed: 80 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React from 'react';
22
import PropTypes from 'prop-types';
3-
import { findDOMNode } from 'react-dom';
3+
import { findDOMNode, createPortal } from 'react-dom';
44
import createReactClass from 'create-react-class';
55
import contains from 'rc-util/lib/Dom/contains';
66
import addEventListener from 'rc-util/lib/Dom/addEventListener';
@@ -22,6 +22,41 @@ function returnDocument() {
2222
const ALL_HANDLERS = ['onClick', 'onMouseDown', 'onTouchStart', 'onMouseEnter',
2323
'onMouseLeave', 'onFocus', 'onBlur'];
2424

25+
const IS_REACT_16 = !!createPortal;
26+
27+
console.log(IS_REACT_16);
28+
29+
const mixins = [];
30+
31+
function getContainer(instance) {
32+
const { props } = instance;
33+
const popupContainer = document.createElement('div');
34+
// Make sure default popup container will never cause scrollbar appearing
35+
// https://github.com/react-component/trigger/issues/41
36+
popupContainer.style.position = 'absolute';
37+
popupContainer.style.top = '0';
38+
popupContainer.style.left = '0';
39+
popupContainer.style.width = '100%';
40+
const mountNode = props.getPopupContainer ?
41+
props.getPopupContainer(findDOMNode(instance)) : props.getDocument().body;
42+
mountNode.appendChild(popupContainer);
43+
return popupContainer;
44+
}
45+
46+
if (!IS_REACT_16) {
47+
mixins.push(
48+
getContainerRenderMixin({
49+
autoMount: false,
50+
51+
isVisible(instance) {
52+
return instance.state.popupVisible;
53+
},
54+
55+
getContainer,
56+
})
57+
);
58+
}
59+
2560
const Trigger = createReactClass({
2661
displayName: 'Trigger',
2762
propTypes: {
@@ -66,30 +101,7 @@ const Trigger = createReactClass({
66101
maskAnimation: PropTypes.string,
67102
},
68103

69-
mixins: [
70-
getContainerRenderMixin({
71-
autoMount: false,
72-
73-
isVisible(instance) {
74-
return instance.state.popupVisible;
75-
},
76-
77-
getContainer(instance) {
78-
const { props } = instance;
79-
const popupContainer = document.createElement('div');
80-
// Make sure default popup container will never cause scrollbar appearing
81-
// https://github.com/react-component/trigger/issues/41
82-
popupContainer.style.position = 'absolute';
83-
popupContainer.style.top = '0';
84-
popupContainer.style.left = '0';
85-
popupContainer.style.width = '100%';
86-
const mountNode = props.getPopupContainer ?
87-
props.getPopupContainer(findDOMNode(instance)) : props.getDocument().body;
88-
mountNode.appendChild(popupContainer);
89-
return popupContainer;
90-
},
91-
}),
92-
],
104+
mixins,
93105

94106
getDefaultProps() {
95107
return {
@@ -154,11 +166,16 @@ const Trigger = createReactClass({
154166
componentDidUpdate(_, prevState) {
155167
const props = this.props;
156168
const state = this.state;
157-
this.renderComponent(null, () => {
169+
const triggerAfterPopupVisibleChange = () => {
158170
if (prevState.popupVisible !== state.popupVisible) {
159171
props.afterPopupVisibleChange(state.popupVisible);
160172
}
161-
});
173+
};
174+
if (!IS_REACT_16) {
175+
this.renderComponent(null, triggerAfterPopupVisibleChange);
176+
} else {
177+
triggerAfterPopupVisibleChange();
178+
}
162179

163180
// We must listen to `mousedown` or `touchstart`, edge case:
164181
// https://github.com/ant-design/ant-design/issues/5804
@@ -186,6 +203,9 @@ const Trigger = createReactClass({
186203
componentWillUnmount() {
187204
this.clearDelayTimer();
188205
this.clearOutsideHandler();
206+
if (IS_REACT_16) {
207+
this.removeContainer();
208+
}
189209
},
190210

191211
onMouseEnter(e) {
@@ -341,6 +361,7 @@ const Trigger = createReactClass({
341361
transitionName={props.popupTransitionName}
342362
maskAnimation={props.maskAnimation}
343363
maskTransitionName={props.maskTransitionName}
364+
ref={this.savePopup}
344365
>
345366
{typeof props.popup === 'function' ? props.popup() : props.popup}
346367
</Popup>
@@ -391,6 +412,12 @@ const Trigger = createReactClass({
391412
}
392413
},
393414

415+
removeContainer() {
416+
if (this._container) {
417+
this._container.parentNode.removeChild(this._container);
418+
}
419+
},
420+
394421
createTwoChains(event) {
395422
const childPros = this.props.children.props;
396423
const props = this.props;
@@ -450,11 +477,18 @@ const Trigger = createReactClass({
450477
this.setPopupVisible(false);
451478
},
452479

480+
savePopup(node) {
481+
if (IS_REACT_16) {
482+
this._component = node;
483+
}
484+
},
485+
453486
render() {
487+
const { popupVisible } = this.state;
454488
const props = this.props;
455489
const children = props.children;
456490
const child = React.Children.only(children);
457-
const newChildProps = {};
491+
const newChildProps = { key: 'target' };
458492
if (this.isClickToHide() || this.isClickToShow()) {
459493
newChildProps.onClick = this.onClick;
460494
newChildProps.onMouseDown = this.onMouseDown;
@@ -482,7 +516,24 @@ const Trigger = createReactClass({
482516
newChildProps.onBlur = this.createTwoChains('onBlur');
483517
}
484518

485-
return React.cloneElement(child, newChildProps);
519+
if (!IS_REACT_16) {
520+
return React.cloneElement(child, newChildProps);
521+
}
522+
523+
if (popupVisible && !this._container) {
524+
this._container = getContainer(this);
525+
}
526+
527+
let portal;
528+
// prevent unmounting when visible change to false
529+
if (popupVisible && !this._component || this._component) {
530+
portal = createPortal(this.getComponent(), this._container);
531+
}
532+
533+
return [
534+
React.cloneElement(child, newChildProps),
535+
portal,
536+
];
486537
},
487538
});
488539

tests/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
/* eslint no-console:0 */
22

3+
import 'core-js/es6/map';
4+
import 'core-js/es6/set';
35
import expect from 'expect.js';
46
import React from 'react';
57
import ReactDOM from 'react-dom';

0 commit comments

Comments
 (0)