简体   繁体   中英

How set react-select width depending on biggest option width?

How set react-select input width depending on biggest option width? Options position is absolute and therefore their size not affect parent div width.

It is example: https://codesandbox.io/s/9o4rkklz14

I need to select width was longest option width.

I've answered this in a few issue threads here and here for more background about complexities and caveats, but here is the gist of the approach.

  1. You need to set the width of the menu to be auto so it will stretch to fit its contents.

  2. onMount, style the menu (height: 0, visibility: hidden) and open the menu with the internal ref method

  3. With the onMenuOpen prop, use a function that waits 1ms, get the width of the listMenuRef, and close/reset the menuIsOpen.

  4. With the calculated width, you can now set the width of the ValueContainer.

The result can be seen here at this codesandbox

Code posted below...

import React, { useState, useRef, useEffect } from "react";
import Select from "react-select";

const App = (props) => {
  const selectRef = useRef();

  const [menuIsOpen, setMenuIsOpen] = useState();
  const [menuWidth, setMenuWidth] = useState();
  const [isCalculatingWidth, setIsCalculatingWidth] = useState(false);

  useEffect(() => {
    if (!menuWidth && !isCalculatingWidth) {
      setTimeout(() => {
        setIsCalculatingWidth(true);
        // setIsOpen doesn't trigger onOpenMenu, so calling internal method
        selectRef.current.select.openMenu("first");
        setMenuIsOpen(true);
      }, 1);
    }
  }, [menuWidth, isCalculatingWidth]);

  const onMenuOpen = () => {
    if (!menuWidth && isCalculatingWidth) {
      setTimeout(() => {
        const width = selectRef.current.select.menuListRef.getBoundingClientRect()
          .width;
        setMenuWidth(width);
        setIsCalculatingWidth(false);

        // setting isMenuOpen to undefined and closing menu
        selectRef.current.select.onMenuClose();
        setMenuIsOpen(undefined);
      }, 1);
    }
  };

  const styles = {
    menu: (css) => ({
      ...css,
      width: "auto",
      ...(isCalculatingWidth && { height: 0, visibility: "hidden" })
    }),
    control: (css) => ({ ...css, display: "inline-flex " }),
    valueContainer: (css) => ({
      ...css,
      ...(menuWidth && { width: menuWidth })
    })
  };

  const options = [
    { label: "Option 1", value: 1 },
    { label: "Option 2", value: 2 },
    { label: "Option 3 is a reallly realllly long boi", value: 3 }
  ];

  return (
    <div>
      <div> Width of menu is {menuWidth}</div>
      <Select
        ref={selectRef}
        onMenuOpen={onMenuOpen}
        options={options}
        styles={styles}
        menuIsOpen={menuIsOpen}
      />
    </div>
  );
};

export default App;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM