Search code examples
reactjsselectavatar

React Select with avatar class component whats wrong here select not populating


Hi I had working select box with avatar on functional aporx. But I need build in functions to change selectbox properties like hidden: true/false, update option data function to add new option data to display selectbox with certain values on fly.

What I wrong here? Render part works as tested with functional version. The class factoring misses something as select box does not get info ether options and avatar to display and no width calculation happening.

Orginal functional code: https://codesandbox.io/s/react-select-longest-option-width-geunu?file=/src/App.js

Class based works but nodatin selectbox. Here is app.js with select.js fiddle: https://codesandbox.io/s/react-select-longest-option-width-forked-plqq0p?file=/src/Select.js

Source:

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

class RtSelect extends React.Component {

  constructor(props) {
    super();
    this.state = {
      info: props.info,
      options: props.options,
      hidden: props.hidden,
      menuIsOpen: false,
      menuWidth: "",
      IsCalculatingWidth: false
    };
    this.selectRef = React.createRef();
    this.onMenuOpen = this.onMenuOpen.bind(this);
  }
  componentDidMount() {
    if (!this.menuWidth && !this.isCalculatingWidth) {
      setTimeout(() => {
        this.setState({IsCalculatingWidth: true});
        // setIsOpen doesn't trigger onOpenMenu, so calling internal method
        this.selectRef.current.select.openMenu();
        this.setState({MenuIsOpen: true});
      }, 1);
    }
  }

  onMenuOpen() {
    if (!this.menuWidth && this.isCalculatingWidth) {
      setTimeout(() => {
        const width = this.selectRef.current.select.menuListRef.getBoundingClientRect()
          .width;
        this.setState({menuWidth: width});
        this.setState({IsCalculatingWidth: false});

        // setting isMenuOpen to undefined and closing menu
        this.selectRef.current.select.onMenuClose();
        this.setState({MenuIsOpen: true});
      }, 1);
    }
  }

  styles = {
    menu: (css) => ({
      ...css,
      width: "auto",
      ...(this.isCalculatingWidth && { height: 0, visibility: "hidden" })
    }),
    control: (css) => ({ ...css, display: "inline-flex " }),
    valueContainer: (css) => ({
      ...css,
      ...(this.menuWidth && { width: this.menuWidth })
    })
  };
  setData (props) {
    this.setState({
      info: props.info, 
      options: props.options, 
      hidden: props.hidden
    })
  }
  render() {
    return (
      <div style={{ display: "flex" }}>
        <div style={{ margin: "8px" }}>{this.info}</div>
        <div>
          <Select
            ref={this.selectRef}
            onMenuOpen={this.onMenuOpen}
            options={this.options}
            menuIsOpen={this.menuIsOpen}
            styles={this.styles}
            isDisabled={this.hidden}
            formatOptionLabel={(options) => (
              <div className="select-option" style={{ display: "flex" }}>
                <div style={{ display: "inline", verticalAlign: "center" }}>
                  <img src={options.avatar} width="30px" alt="Avatar" />
                </div>
                &nbsp;
                <div style={{ display: "inline", marginLeft: "10px" }}>
                  <span>{options.label}</span>
                </div>
              </div>
            )}
          />
        </div>
      </div>
    );
  }
}

export default RtSelect;

Solution

  • Got it working!

    I had removed "undefined" from onOpen setState function. I compared those 2 fiddles and finally got it working.

    
            // setting isMenuOpen to undefined and closing menu
            this.selectRef.current.select.onMenuClose();
            this.setState({MenuIsOpen: undefined});