# Using Selectlist in React

Selectlist is an upcoming element that replaces the native select element with a fully stylable and customizable one, while still keeping all the native interactions and accessibility features. It's a sorely needed improvement and will let you do away with all your custom select implementations.

> Selectlist is an experimental feature. **It's still being worked on and you can't use it in browsers yet**, unless you use Polypane (...or a Chromium based browser where you have experimental features turned on.)

This isn't a full exploration of what `selectlist` is and can do, but a quick explainer of how to get `selectlist` to play nicely with React. We ran into issues while replacing some of the `select` elements in the Polypane UI, which is built with React, and we hope this prevents you from running into the same issues. For a nice introduction, check out Hidde's article [Two levels of customising `<selectlist>`](https://hidde.blog/custom-select-with-selectlist/) and for a full explainer, head over to [OpenUI](https://open-ui.org/components/selectlist/) which is where the element is being developed.

## Select in React

When you want to do something when the value in your regular select changes in th regular React way, you use the `onChange` prop:

```jsx
<select onChange={(e) => doSomething(e)}>
  <option value="hex">Hex</option>
  <option value="rgb">Rgb</option>
  <option value="hsl">HSL</option>
</select>
```

And every time a user picks a new option, the onChange is fired and you can handle whatever you need to do with the event.

## Selectlist in React

To "migrate" from `select` to `selectlist`, you'd expect to be able to just swap them out:

```jsx
<selectlist onChange={(e) => doSomething(e)}>
  <option value="hex">Hex</option>
  <option value="rgb">Rgb</option>
  <option value="hsl">HSL</option>
</selectlist>
```

Unfortunately, that's not the case. When you do that you'll notice that while the `selectlist` value updates, `onChange` doesn't fire. That's because the onChange prop is a React concept, not a different notation for the DOM native `change` event.

React has specific code that calls the `onChange` function whenever the `change` event fires on `select` elements, but it doesn't know about `selectlist` yet so the `onChange` on `selectlist` doesn't get called.

To make it work, we need to add the listeners ourselves using useEffect and useRef:

```jsx
import { useEffect, useRef } from 'react';

const OurComponent = () => {
  const selectlist = useRef();

  useEffect(() => {
    const currentSelectlist = selectlist.current;
    currentSelectlist.addEventListener('change', doSomething);

    return () => {
      currentSelectlist.removeEventListener('change', doSomething);
    };
  }, []);

  function doSomething(e) {
    // do something with the event
  }

  return (
    <selectlist ref={selectlist}>
      <option value="hex">Hex</option>
      <option value="rgb">Rgb</option>
      <option value="hsl">HSL</option>
    </selectlist>
  );
};
```

We use a ref to get the actual DOM element of the `selectlist`, and then use `useEffect` to add (and remove) event listeners to it manually. The listener doesn't need to change when we update the element, so we add an empty array as the dependency array of the useEffect.

To prevent event listeners from hanging around and taking up memory after we've removed the element from the DOM, we also add a return function to the `useEffect` to remove the event listener when the component unmounts.

## Selectlist as a separate React component

You probably don't want to add that useEffect to each component you use a Selectlist in, so instead you can extract it into its own component:

```jsx
import { useEffect, useRef } from 'react';

const Selectlist = ({ onChange, children, value }) => {
  const ref = useRef();

  useEffect(() => {
    const selectlist = ref.current;
    selectlist.addEventListener('change', onChange);
    return () => selectlist.removeEventListener('change', onChange);
  }, [onChange]);

  return (
    <selectlist ref={ref} value={value}>
      {children}
    </selectlist>
  );
};

// and then use it like this:
const OurComponent = () => {
  // do your domain specific stuff

  return (
    <div>
      {/* your other component parts */}
      <Selectlist onChange={doSomething} value={value}>
        <option value="hex">Hex</option>
        <option value="rgb">Rgb</option>
        <option value="hsl">HSL</option>
      </Selectlist>
    </div>
  );
};
```

And that's how you can use `selectlist` in React.

Keep in mind that `selectlist` isn't something you can use in the wild and have work for your visitors, and that it's still in development so things might change.

We have the luxury of determining our own browser support and we're happily using it inside Polypane to improve how our Selects work without sacrificing on accessibility or existing user expectations. If you want to play around with `selectlist` too, [try Polypane for free](/).

---

Polypane is the browser built for developers and designers — try it at https://polypane.app.
