Skip to content

Commit 5337b18

Browse files
committed
use getContainerRenderMixin
1 parent 0cdfc92 commit 5337b18

File tree

4 files changed

+109
-83
lines changed

4 files changed

+109
-83
lines changed

HISTORY.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
# History
22
----
33

4+
## 1.7.0 / 2016-07-18
5+
6+
- use getContainerRenderMixin from 'rc-util'
7+
48
## 1.6.0 / 2016-05-26
59

610
- support popup as function

examples/simple.js

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,24 @@ const Test = React.createClass({
105105
console.log('tooltip', visible);
106106
},
107107

108+
destroy() {
109+
this.setState({
110+
destroyed: true,
111+
});
112+
},
113+
114+
destroyPopupOnHide(e) {
115+
this.setState({
116+
destroyPopupOnHide: e.target.checked,
117+
});
118+
},
119+
108120
render() {
109121
const state = this.state;
110122
const trigger = state.trigger;
123+
if (state.destroyed) {
124+
return null;
125+
}
111126
return (<div >
112127
<div style={{ margin: '10px 20px' }}>
113128
<label>
@@ -165,6 +180,15 @@ const Test = React.createClass({
165180
/>
166181
click
167182
</label>
183+
&nbsp;&nbsp;&nbsp;&nbsp;
184+
<label>
185+
<input
186+
checked={!!this.state.destroyPopupOnHide}
187+
type="checkbox"
188+
onChange={this.destroyPopupOnHide}
189+
/>
190+
destroyPopupOnHide
191+
</label>
168192
<br/>
169193
<label>
170194
offsetX:
@@ -183,17 +207,19 @@ const Test = React.createClass({
183207
style={{ width: 50 }}
184208
/>
185209
</label>
210+
&nbsp;&nbsp;&nbsp;&nbsp;
211+
<button onClick={this.destroy}>destroy</button>
186212
</div>
187213
<div style={{ margin: 100, position: 'relative' }}>
188214
<Trigger
189215
getPopupContainer={undefined && getPopupContainer}
190216
popupAlign={getPopupAlign(state)}
191217
mouseEnterDelay={0}
192218
popupPlacement={state.placement}
219+
destroyPopupOnHide={this.state.destroyPopupOnHide}
193220
// zIndex={40}
194221
// mask
195222
// maskAnimation="fade"
196-
// destroyPopupOnHide
197223
mouseLeaveDelay={0.1}
198224
action={Object.keys(state.trigger)}
199225
builtinPlacements={builtinPlacements}

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "rc-trigger",
3-
"version": "1.6.3",
3+
"version": "1.7.0",
44
"description": "base abstract trigger component for react",
55
"keywords": [
66
"react",
@@ -55,6 +55,6 @@
5555
"dependencies": {
5656
"rc-align": "2.x",
5757
"rc-animate": "2.x",
58-
"rc-util": "3.x"
58+
"rc-util": "^3.3.x"
5959
}
6060
}

src/Trigger.jsx

Lines changed: 76 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import contains from 'rc-util/lib/Dom/contains';
55
import addEventListener from 'rc-util/lib/Dom/addEventListener';
66
import Popup from './Popup';
77
import { getAlignFromPlacement, getPopupClassNameFromAlign } from './utils';
8+
import getContainerRenderMixin from 'rc-util/lib/getContainerRenderMixin';
89

910
function noop() {
1011
}
@@ -50,6 +51,56 @@ const Trigger = React.createClass({
5051
maskAnimation: PropTypes.string,
5152
},
5253

54+
mixins: [
55+
getContainerRenderMixin({
56+
autoMount: false,
57+
58+
isVisible(instance) {
59+
return instance.state.popupVisible;
60+
},
61+
62+
getContainer(instance) {
63+
const popupContainer = document.createElement('div');
64+
const mountNode = instance.props.getPopupContainer ?
65+
instance.props.getPopupContainer(findDOMNode(instance)) : document.body;
66+
mountNode.appendChild(popupContainer);
67+
return popupContainer;
68+
},
69+
70+
getComponent(instance) {
71+
const { props, state } = instance;
72+
const mouseProps = {};
73+
if (instance.isMouseEnterToShow()) {
74+
mouseProps.onMouseEnter = instance.onMouseEnter;
75+
}
76+
if (instance.isMouseLeaveToHide()) {
77+
mouseProps.onMouseLeave = instance.onMouseLeave;
78+
}
79+
return (<Popup
80+
prefixCls={props.prefixCls}
81+
destroyPopupOnHide={props.destroyPopupOnHide}
82+
visible={state.popupVisible}
83+
className={props.popupClassName}
84+
action={props.action}
85+
align={instance.getPopupAlign()}
86+
onAlign={props.onPopupAlign}
87+
animation={props.popupAnimation}
88+
getClassNameFromAlign={instance.getPopupClassNameFromAlign}
89+
{...mouseProps}
90+
getRootDomNode={instance.getRootDomNode}
91+
style={props.popupStyle}
92+
mask={props.mask}
93+
zIndex={props.zIndex}
94+
transitionName={props.popupTransitionName}
95+
maskAnimation={props.maskAnimation}
96+
maskTransitionName={props.maskTransitionName}
97+
>
98+
{typeof props.popup === 'function' ? props.popup() : props.popup}
99+
</Popup>);
100+
},
101+
}),
102+
],
103+
53104
getDefaultProps() {
54105
return {
55106
prefixCls: 'rc-trigger-popup',
@@ -92,54 +143,42 @@ const Trigger = React.createClass({
92143
});
93144
},
94145

95-
componentWillReceiveProps(nextProps) {
96-
if ('popupVisible' in nextProps) {
146+
componentWillReceiveProps({ popupVisible }) {
147+
if (popupVisible !== undefined) {
97148
this.setState({
98-
popupVisible: !!nextProps.popupVisible,
149+
popupVisible,
99150
});
100151
}
101152
},
102153

103-
componentDidUpdate(prevProps, prevState) {
154+
componentDidUpdate(_, prevState) {
104155
const props = this.props;
105156
const state = this.state;
106-
if (this.popupRendered) {
107-
const self = this;
108-
ReactDOM.unstable_renderSubtreeIntoContainer(this,
109-
this.getPopupElement(),
110-
this.getPopupContainer(), function mounted() {
111-
self.popupInstance = this;
112-
if (prevState.popupVisible !== state.popupVisible) {
113-
props.afterPopupVisibleChange(state.popupVisible);
114-
}
115-
});
116-
if (this.isClickToHide()) {
117-
if (state.popupVisible) {
118-
if (!this.clickOutsideHandler) {
119-
this.clickOutsideHandler = addEventListener(document,
120-
'mousedown', this.onDocumentClick);
121-
this.touchOutsideHandler = addEventListener(document,
122-
'touchstart', this.onDocumentClick);
123-
}
124-
return;
125-
}
157+
this.renderComponent(() => {
158+
if (prevState.popupVisible !== state.popupVisible) {
159+
props.afterPopupVisibleChange(state.popupVisible);
126160
}
127-
if (this.clickOutsideHandler) {
128-
this.clickOutsideHandler.remove();
129-
this.touchOutsideHandler.remove();
130-
this.clickOutsideHandler = null;
131-
this.touchOutsideHandler = null;
161+
});
162+
if (this.isClickToHide()) {
163+
if (state.popupVisible) {
164+
if (!this.clickOutsideHandler) {
165+
this.clickOutsideHandler = addEventListener(document,
166+
'mousedown', this.onDocumentClick);
167+
this.touchOutsideHandler = addEventListener(document,
168+
'touchstart', this.onDocumentClick);
169+
}
170+
return;
132171
}
133172
}
173+
if (this.clickOutsideHandler) {
174+
this.clickOutsideHandler.remove();
175+
this.touchOutsideHandler.remove();
176+
this.clickOutsideHandler = null;
177+
this.touchOutsideHandler = null;
178+
}
134179
},
135180

136181
componentWillUnmount() {
137-
const popupContainer = this.popupContainer;
138-
if (popupContainer) {
139-
ReactDOM.unmountComponentAtNode(popupContainer);
140-
popupContainer.parentNode.removeChild(popupContainer);
141-
this.popupContainer = null;
142-
}
143182
this.clearDelayTimer();
144183
if (this.clickOutsideHandler) {
145184
this.clickOutsideHandler.remove();
@@ -223,8 +262,8 @@ const Trigger = React.createClass({
223262

224263
getPopupDomNode() {
225264
// for test
226-
if (this.popupInstance) {
227-
return this.popupInstance.isMounted() ? this.popupInstance.getPopupDomNode() : null;
265+
if (this._component) {
266+
return this._component.isMounted() ? this._component.getPopupDomNode() : null;
228267
}
229268
return null;
230269
},
@@ -233,16 +272,6 @@ const Trigger = React.createClass({
233272
return ReactDOM.findDOMNode(this);
234273
},
235274

236-
getPopupContainer() {
237-
if (!this.popupContainer) {
238-
this.popupContainer = document.createElement('div');
239-
const mountNode = this.props.getPopupContainer ?
240-
this.props.getPopupContainer(findDOMNode(this)) : document.body;
241-
mountNode.appendChild(this.popupContainer);
242-
}
243-
return this.popupContainer;
244-
},
245-
246275
getPopupClassNameFromAlign(align) {
247276
const className = [];
248277
const props = this.props;
@@ -265,38 +294,6 @@ const Trigger = React.createClass({
265294
return popupAlign;
266295
},
267296

268-
getPopupElement() {
269-
const { props, state } = this;
270-
const mouseProps = {};
271-
if (this.isMouseEnterToShow()) {
272-
mouseProps.onMouseEnter = this.onMouseEnter;
273-
}
274-
if (this.isMouseLeaveToHide()) {
275-
mouseProps.onMouseLeave = this.onMouseLeave;
276-
}
277-
return (<Popup
278-
prefixCls={props.prefixCls}
279-
destroyPopupOnHide={props.destroyPopupOnHide}
280-
visible={state.popupVisible}
281-
className={props.popupClassName}
282-
action={props.action}
283-
align={this.getPopupAlign()}
284-
onAlign={props.onPopupAlign}
285-
animation={props.popupAnimation}
286-
getClassNameFromAlign={this.getPopupClassNameFromAlign}
287-
{...mouseProps}
288-
getRootDomNode={this.getRootDomNode}
289-
style={props.popupStyle}
290-
mask={props.mask}
291-
zIndex={props.zIndex}
292-
transitionName={props.popupTransitionName}
293-
maskAnimation={props.maskAnimation}
294-
maskTransitionName={props.maskTransitionName}
295-
>
296-
{typeof props.popup === 'function' ? props.popup() : props.popup}
297-
</Popup>);
298-
},
299-
300297
setPopupVisible(popupVisible) {
301298
this.clearDelayTimer();
302299
if (this.state.popupVisible !== popupVisible) {
@@ -365,7 +362,6 @@ const Trigger = React.createClass({
365362
},
366363

367364
render() {
368-
this.popupRendered = this.popupRendered || this.state.popupVisible;
369365
const props = this.props;
370366
const children = props.children;
371367
const child = React.Children.only(children);

0 commit comments

Comments
 (0)