Skip to content

Commit

Permalink
[Popper] Fix to defer setting of exited state to Transition component (
Browse files Browse the repository at this point in the history
…#15250)

* [Popper] Fix to defer setting of exited state to Transition component

* [Popper] Use id selector in tests

* higher level test

* [Popper] Specify with which keepMounted value we're testing
  • Loading branch information
Sharakai authored and oliviertassinari committed Apr 11, 2019
1 parent c5700e0 commit 2cc52c5
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 18 deletions.
23 changes: 6 additions & 17 deletions packages/material-ui/src/Popper/Popper.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,23 +66,6 @@ class Popper extends React.Component {
this.handleClose();
}

static getDerivedStateFromProps(nextProps) {
if (nextProps.open) {
return {
exited: false,
};
}

if (!nextProps.transition) {
// Otherwise let handleExited take care of marking exited.
return {
exited: true,
};
}

return null;
}

handleOpen = () => {
const { anchorEl, modifiers, open, placement, popperOptions = {}, disablePortal } = this.props;
const popperNode = this.tooltipRef.current;
Expand Down Expand Up @@ -126,6 +109,10 @@ class Popper extends React.Component {
}
};

handleEnter = () => {
this.setState({ exited: false });
};

handleExited = () => {
this.setState({ exited: true });
this.handleClose();
Expand Down Expand Up @@ -173,6 +160,7 @@ class Popper extends React.Component {
if (transition) {
childProps.TransitionProps = {
in: open,
onEnter: this.handleEnter,
onExited: this.handleExited,
};
}
Expand Down Expand Up @@ -305,6 +293,7 @@ Popper.propTypes = {

Popper.defaultProps = {
disablePortal: false,
keepMounted: false,
placement: 'bottom',
transition: false,
};
Expand Down
43 changes: 43 additions & 0 deletions packages/material-ui/src/Popper/Popper.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,49 @@ describe('<Popper />', () => {
});
});

describe('prop: keepMounted', () => {
describe('by default', () => {
// Test case for https://github.com/mui-org/material-ui/issues/15180
it('should remove the transition children in the DOM when closed whilst transition status is entering', () => {
const children = <p>Hello World</p>;

class OpenClose extends React.Component {
state = {
open: false,
};

handleClick = () => {
this.setState({ open: true }, () => {
this.setState({ open: false });
});
};

render() {
return (
<div>
<button type="button" onClick={this.handleClick}>
Toggle Tooltip
</button>
<Popper {...defaultProps} open={this.state.open} transition>
{({ TransitionProps }) => (
<Grow {...TransitionProps}>
<span>{children}</span>
</Grow>
)}
</Popper>
</div>
);
}
}

const wrapper = mount(<OpenClose />);
assert.strictEqual(wrapper.contains(children), false);
wrapper.find('button').simulate('click');
assert.strictEqual(wrapper.contains(children), false);
});
});
});

describe('prop: transition', () => {
it('should work', () => {
const wrapper = mount(
Expand Down
2 changes: 1 addition & 1 deletion pages/api/popper.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Poppers rely on the 3rd party library [Popper.js](https://github.com/FezVrasta/p
| <span class="prop-name required">children&nbsp;*</span> | <span class="prop-type">union:&nbsp;node&nbsp;&#124;<br>&nbsp;func<br></span> | | Popper render function or node. |
| <span class="prop-name">container</span> | <span class="prop-type">union:&nbsp;object&nbsp;&#124;<br>&nbsp;func<br></span> | | A node, component instance, or function that returns either. The `container` will passed to the Modal component. By default, it uses the body of the anchorEl's top-level document object, so it's simply `document.body` most of the time. |
| <span class="prop-name">disablePortal</span> | <span class="prop-type">bool</span> | <span class="prop-default">false</span> | Disable the portal behavior. The children stay within it's parent DOM hierarchy. |
| <span class="prop-name">keepMounted</span> | <span class="prop-type">bool</span> | | Always keep the children in the DOM. This property can be useful in SEO situation or when you want to maximize the responsiveness of the Popper. |
| <span class="prop-name">keepMounted</span> | <span class="prop-type">bool</span> | <span class="prop-default">false</span> | Always keep the children in the DOM. This property can be useful in SEO situation or when you want to maximize the responsiveness of the Popper. |
| <span class="prop-name">modifiers</span> | <span class="prop-type">object</span> | | Popper.js is based on a "plugin-like" architecture, most of its features are fully encapsulated "modifiers".<br>A modifier is a function that is called each time Popper.js needs to compute the position of the popper. For this reason, modifiers should be very performant to avoid bottlenecks. To learn how to create a modifier, [read the modifiers documentation](https://github.com/FezVrasta/popper.js/blob/master/docs/_includes/popper-documentation.md#modifiers--object). |
| <span class="prop-name required">open&nbsp;*</span> | <span class="prop-type">bool</span> | | If `true`, the popper is visible. |
| <span class="prop-name">placement</span> | <span class="prop-type">enum:&nbsp;'bottom-end', 'bottom-start', 'bottom', 'left-end', 'left-start', 'left', 'right-end', 'right-start', 'right', 'top-end', 'top-start', 'top'<br></span> | <span class="prop-default">'bottom'</span> | Popper placement. |
Expand Down

0 comments on commit 2cc52c5

Please sign in to comment.