37

Using React-Select (version 2) I would like to have custom designed (select) options.

The documentation suggests that Replacing Components would be a method that I could use to achieve this.

Unfortunately I'm unable to find examples that show implementations of this feature.

Is there anyone that could present to me usage of this feature whereby you would have a simple custom option (perhaps a label and value that also includes an SVG graphic to the left of each option label).

Many thanks in advance

user2190690
  • 1,744
  • 4
  • 24
  • 31

4 Answers4

95

For a majority of use cases, you probably don't need to replace the full Option component. If you're looking to stay with the same overall structure and look and feel of the Option, but you want to display several blocks of text, or an image, or some other special treatment to the body of each option, there is an easier way.

That's to use the formatOptionLabel render prop.

import React from "react";
import ReactDOM from "react-dom";
import Select from "react-select";

const options = [
  { value: "Abe", label: "Abe", customAbbreviation: "A" },
  { value: "John", label: "John", customAbbreviation: "J" },
  { value: "Dustin", label: "Dustin", customAbbreviation: "D" }
];

const formatOptionLabel = ({ value, label, customAbbreviation }) => (
  <div style={{ display: "flex" }}>
    <div>{label}</div>
    <div style={{ marginLeft: "10px", color: "#ccc" }}>
      {customAbbreviation}
    </div>
  </div>
);

const CustomControl = () => (
  <Select
    defaultValue={options[0]}
    formatOptionLabel={formatOptionLabel}
    options={options}
  />
);

ReactDOM.render(<CustomControl />, document.getElementById("root"));

https://codesandbox.io/embed/reactselect-formatoptionlabel-bde1q

https://react-select.com/props - search for formatOptionLabel

duhseekoh
  • 1,263
  • 10
  • 13
  • Nice trick. Is it possible to somehow format the options when they've been selected so they differ from when they are in the dropdown list? I'm using a multi select and in the actual drop down I would like to have more information than when the value has been selected. – Tomas Jansson May 20 '21 at 21:54
  • 6
    Probably way too late for your project but maybe this helps other people. You can do this: `const formatOptionLabel = ({ value, label, customAbbreviation }, {context}) => (` If context is "menu", it is an item, and "value" is the selected value – krizzzn Nov 12 '21 at 16:41
34

You can replace any component by including your override in the components property.

<Select components={{Option: MyOption}} />

Something like:

const MyOption = props => {
  const { innerProps, innerRef } = props;
  return (
    <article ref={innerRef} {...innerProps} className="custom-option">
      <h4>{props.data.artist}</h4>
      <div className="sub">{props.data.title} </div>
    </article>
  );
};

<Select components={{Option: MyOption}} />

The innerRef and innerProps properties are very important, as they carry forward things like the hover and onClick needed by the Option. The data in props is where your option data is.

Steve -Cutter- Blades
  • 5,057
  • 2
  • 26
  • 40
  • Thank you for your reply. What if I wanted to customise the appearance of the initial default state of the Select. Would that be: In your code there are no references to your MyOption. Could you say why you use MyOption, ie after 'Option: '? This component seems great...it also seems like it could do with some upgraded documentation :-) Thanks for any help you can provide :-) – user2190690 Oct 17 '18 at 19:38
  • that was just an example, if you had named your component something other than 'Option'. As far as customizing the appearance, it depends on the appearance of which component (Select is made of many pieces). The documentation is a fantastic resource. – Steve -Cutter- Blades Oct 17 '18 at 20:59
12

Generally, you indeed want to use formatOptionLabel prop (no extra component). But in case you don't, you may override the Option component this way:

import Select, { components } from 'react-select';

const CustomOption = ({ children, ...props }) => {
  return (
    <components.Option {...props}>
      <img src={...} />
      {children}
    </components.Option>
  );
};

function App() {
  return (
    <Select components={{Option: CustomOption}} ... />
  );
}

Here I reuse the stock component (components.Option). This way I don't need to care about innerRef or something.

https://codesandbox.io/s/react-select-item-icon-2z3tb

x-yuri
  • 16,722
  • 15
  • 114
  • 161
1

If you want to style your option when it has been selected you can use a custom option like so:

const customOption = (props) => (
{props.isSelected ? (
  <img className="custom-option__img" src={IconCheck} alt="" />
) : (
  ''
)}
);