1

I am using react-select. But I don't know how to get the value of the currently highlighted option from the list options.

E.g. if a user pressed the key down or up button, I want to know which option is selected.

select listbox

I haven't found any usable props in the documentation.

Not looking solutions like below. Get value of highlighted option in React-Select

Chris
  • 6,331
  • 1
  • 21
  • 25
Mike Phils
  • 3,475
  • 5
  • 24
  • 45
  • 1
    what do you mean? bit confused. you mean that your search text should be highlighted at the select options that are filtered? – Apostolos Jul 13 '21 at 13:18
  • I mean If I search I get list. And User keyup or down. Highlighted value I need.Update questions with image. – Mike Phils Jul 13 '21 at 13:22

2 Answers2

1

Sadly the library doesn't provide such a feature. However it applies the [class-prefix]__option--is-focused to the option that is focused. You can then easily get the value you want by checking classes change in pure Javascript.

This answer implement the class ClassWatcher that enable you to check class addition or removal on a specific node like:

new ClassWatcher(targetNode, 'your-class', onClassAdd, onClassRemoval)

So you could add this watcher to each options of the select by using querySelectorAll on the ref of the select. First step is to initialised the component with a few options and some states like isMenuOpen, focusedValue and the selectedOption:

const OPTIONS = [
  { value: "chocolate", label: "Chocolate" },
  { value: "strawberry", label: "Strawberry" },
  { value: "vanilla", label: "Vanilla" }
];

export default function App() {
  const [isMenuOpen, setIsMenuOpen] = React.useState(false);
  const [focusedValue, setFocusedValue] = React.useState("");
  const [selectedOption, setSelectedOption] = React.useState(null);
  const ref = React.useRef(null);

  return (
    <div className="App">
      <p>Focused value: {focusedValue}</p>
      <Select
        ref={ref}
        classNamePrefix="my-select"
        value={selectedOption}
        onChange={setSelectedOption}
        options={OPTIONS}
        isMenuOpen={isMenuOpen}
        onMenuOpen={() => setIsMenuOpen(true)}
        onMenuClose={() => {
          setFocusedValue("");
          setIsMenuOpen(false);
        }}
      />
    </div>
  );
}

Now we can use ClassWatcher to update the focusedValue state when the class my-select__option--is-focused change. This as to be done when the ref is not null and when the menu is open so we can use a useEffect hook for that:

  React.useEffect(() => {
    if (ref && isMenuOpen) {
      const menu = ref.current.select.menuListRef;
      const options = menu.querySelectorAll(".my-select__option");

      // add class watcher to each options
      options.forEach((option, index) => {
        new ClassWatcher(
          option,
          "my-select__option--is-focused",
          () => setFocusedValue(OPTIONS[index].value),
          () => {}
        );
      });
    }
  }, [ref, isMenuOpen]);

You can check here the complete example:

Edit nice-feather-di684

johannchopin
  • 13,720
  • 10
  • 55
  • 101
  • I didn't get 'select' in 'ref.current.select'. In dom i didn't find class as 'my-select__option'.Even on react-select offical site they dont have this class, when I debugged. – Mike Phils Jul 16 '21 at 14:59
  • 1
    @MikePhils Did you add the `classNamePrefix="my-select"` prop to the `Select` component? The codesandbox uses `react-select` version4.3.1 and it works properly. – johannchopin Jul 16 '21 at 15:26
  • ref dont have select. Mine is version 2+ – Mike Phils Jul 16 '21 at 15:35
  • Is it possible to upgrade it because this version is really old. – johannchopin Jul 16 '21 at 15:37
  • Unfortunately not, using in many place in our project – Mike Phils Jul 16 '21 at 15:51
  • 1
    Ok please next time provide this information in first place. I will try to see how to implement this with this old version. – johannchopin Jul 16 '21 at 16:07
  • My bad 'react-select: 2.4.2'.Basically let say when hit enter then options highlighted selected.Something like that. Example let say If I hit space button then highlighted must selected. – Mike Phils Jul 16 '21 at 16:22
  • Mmh just checked with v2.4.2 and it's also working fine, you can see that when you focus an element its value is showned at the top https://codesandbox.io/s/muddy-wildflower-ct7tl?file=/src/App.js – johannchopin Jul 17 '21 at 09:05
  • [class-prefix]__option--is-focused this is important. – Mike Phils Jul 21 '21 at 16:30
0

The Option component has an isFocused prop you that could be used. I'm looking at injecting a ref into the custom option prop and whenever that option is focus, update the ref to the value of that option.

import React from "react";
import Select, { components, OptionProps } from "react-select";
import { ColourOption, colourOptions } from "./docs/data";

export default () => {
  const focusdRef = React.useRef(colourOptions[4]);

  const Option = (props: OptionProps<ColourOption>) => {
    const { isFocused, data } = props;
    if (isFocused) focusdRef.current = data;
    return <components.Option {...props} />;
  };

  return (
    <Select
      closeMenuOnSelect={false}
      components={{ Option }}
      styles={{
        option: (base) => ({
          ...base,
          border: `1px dotted ${colourOptions[2].color}`,
          height: "100%"
        })
      }}
      defaultValue={colourOptions[4]}
      options={colourOptions}
      onKeyDown={(e) => {
        if (e.key === "ArrowRight") {
          console.log(focusdRef.current);
        }
      }}
    />
  );
};

So here whenever you press the right arrow, you have access to the current focused value.

code sandbox:

Edit codesandboxer-example (forked)

sirclesam
  • 2,109
  • 17
  • 13