-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Description
I've set a maxMenuHeight on an Async component, but after the options are loaded, the max height is not calculated and instead is set to the maxMenuHeight that is provided. This causes the menu to be cut off by the bottom of the screen and not flip to the top of the select when enough options are returned. I would expect the menu to not flow beyond the window after the options are loaded and still not flip to the top if minMenuHeight has not been reached either.
I was able to write a hack around this by adding a custom component for Menu and forcing innerRef to be called (so that getPlacement on MenuPlacer will be triggered and the max height recalculated) whenever the supplied options have changed (using an MD5 hash for this to ensure that the options truly have changed).
Version: 3.1.0
Test Case:
import ReactSelectAsync from "react-select/async";
export default function TestCase() {
return (
<ReactSelectAsync
maxMenuHeight={2000}
loadOptions={() => new Promise((resolve) => {
setTimeout(function() {
const ret = [];
for (let i = 0; i < 50; i++) {
ret.push({
value: i,
label: `Item ${i}`
});
}
resolve(ret);
}, 1000);
}}
/>
);
}My Workaround:
import { components } from "react-select";
import { MD5 } from "object-hash";
export class CustomMenu extends React.Component {
_isFirstRender = true;
_menuRef = React.createRef();
render() {
const { children, ...props } = this.props;
return (
<components.Menu {...props} innerRef={this._innerRef}>
{children}
</components.Menu>
);
}
componentDidUpdate() {
const optionsHash = MD5(this.props.options);
if (this._prevOptionsHash !== optionsHash) {
this._prevOptionsHash = optionsHash;
if (!this._isFirstRender && this._menuRef.current != null) {
this.props.innerRef(this._menuRef.current);
}
}
this._isFirstRender = false;
}
_innerRef = (...args) => {
processDomRef(this._menuRef, ...args);
this.props.innerRef(...args);
};
}