Skip to content

Async menu list height remains unchanged after options loaded #4146

@bsara

Description

@bsara

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);
  };
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    issue/bug-unconfirmedIssues that describe a bug that hasn't been confirmed by a maintainer yetissue/reviewedIssue has recently been reviewed (mid-2020)menu-bugAddresses menu positioning, scrolling, or general interactions

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions