How can I create nested option groups in React Select (V2)?

10,846

For anyone who comes here with a similar need, I implemented this recursive work-around.

const renderNestedOption = (props, label, nestedOptions) => {
  const {
    cx,
    getStyles,
    innerProps,
    selectOption,   
  } = props;

  // Will be applied to nested optgroup headers 
  const nestedLabelClassName = cx(
    css(getStyles('groupHeading', props)),
    { option: true },
    'nested-optgroup-label',
  );    

  return (
    <div className="nested-optgroup">
      <div className={nestedLabelClassName}>
        {label}
      </div>
      {nestedOptions.map((nestedOption) => {
        if (nestedOption.options) {
          // Read below
          // Read above
          return renderNestedOption(props, nestedOption.label, nestedOption.options);
        }

        const nestedInnerProps = innerProps;
        nestedInnerProps.onClick = () => selectOption(nestedOption);
        return (
          <div className="nested-optgroup-option" key={nestedOption.value}>
            <components.Option {...props} innerProps={nestedInnerProps}>
              {nestedOption.label}
            </components.Option>
          </div>
        );
      })}
    </div>   
  ); 
};

const Option = (props) => {
  const {
    children,
    data,
  } = props;
  const nestedOptions = data.options;

  if (nestedOptions) {
    const label = data.label;
    return renderNestedOption(props, label, nestedOptions);
  }

  return (
    <components.Option {...props}>
      {children}
    </components.Option>
  );
};

Then in your select component, replace the Option component with the custom Option component we just created.

EDIT

There's an open pull request to support this functionality: https://github.com/JedWatson/react-select/pull/2750

Share:
10,846
Andrea Rosales
Author by

Andrea Rosales

I love programming, computer architecture and physics.

Updated on June 14, 2022

Comments

  • Andrea Rosales
    Andrea Rosales almost 2 years

    In React-Select V2, we're able to create option groups by passing an options param like so:

    options = [
        { label: 'Group', options: [
            { label: 'Option 1', value: '1' },
            { label: 'Option 2', value: '2' }
        ]}
    ]
    

    I need to be able to go another layer deep, something like:

    options = [
        { label: 'Group', options: [
            { label: 'Option 1', value: '1' },
            { label: 'Option 2', options: [
                { label: 'Option 2-a', value: '2a' },
                { label: 'Option 2-b', value: '2b' },
            ]}
        ]}
    ]
    

    Which would display the options "Option 2-a" and "Option 2-b" in a group under "Option 2". The approach above doesn't work out of the box, so I want to know if there's a way to create nested groups in React-Select V2.

    • Steve -Cutter- Blades
      Steve -Cutter- Blades over 5 years
      This is an interesting use case that I don't think React-Select currently supports. Would be a great feature request though.
    • Laura
      Laura over 5 years
      agreed with @Steve-Cutter-Blades you should do a feature request. As in V2, groups have been implemented, it could be a finish
    • Waweru Kamau
      Waweru Kamau almost 4 years
      This issue has been a requested feature for react-select and has now been implemented in this PR. You can find a working example here codesandbox.io/s/react-codesandboxer-example-8xxyx?file=/…