skip to Main Content

I am trying to add an edit button (which currently triggers an alert) to my react-select component. However, this makes the newly added button unclickable; instead, it opens the react-select menu. Stopping propagation does not solve the issue.

const CustomOption = (props) => {
  const handleEdit = (e) => {
    e.stopPropagation();
    alert("This is working like I want");
  };

  return (
    <components.Option {...props}>
      <div className="test">
        <span>{props.children}</span>
        <button onClick={handleEdit}>Edit</button>
      </div>
    </components.Option>
  );
};
export default function App() {
  const option = [
    { value: "Spring", label: "Spring" },
    { value: "Summer", label: "Summer" },
    { value: "Autumn", label: "Autumn" },
    { value: "Winter", label: "Winter" },
  ];

  return (
    <div className="App">
      <Select
        className="dropdown"
        options={option}
        components={{ SingleValue: CustomSingleValue }}
      />
    </div>
  );
}

Question: Why doesn’t the button inside CustomSingleValue work (while the one inside CustomOption does), and how can I fix it?

Code SandBox

This is especially frustrating because CustomOption, which uses the exact same code, works fine.

Working vs not working

Full code including working CustomOption:

// This isn't working like I want
const CustomSingleValue = (props) => {
  const handleEdit = (e) => {
    e.stopPropagation();
    alert("This I can't click");
  };

  return (
    <components.SingleValue {...props}>
      <div className="test">
        <span>{props.children}</span>
        <div>
          <button onClick={handleEdit}>Edit</button>
        </div>
      </div>
    </components.SingleValue>
  );
};

// This is working how I want
const CustomOption = (props) => {
  const handleEdit = (e) => {
    e.stopPropagation();
    alert("This is working like I want");
  };

  return (
    <components.Option {...props}>
      <div className="test">
        <span>{props.children}</span>
        <button onClick={handleEdit}>Edit</button>
      </div>
    </components.Option>
  );
};
export default function App() {
  const option = [
    { value: "Spring", label: "Spring" },
    { value: "Summer", label: "Summer" },
    { value: "Autumn", label: "Autumn" },
    { value: "Winter", label: "Winter" },
  ];

  return (
    <div className="App">
      <Select
        className="dropdown"
        options={option}
        placeholder="Click on a option and then try to click the edit button"
        components={{ SingleValue: CustomSingleValue, Option: CustomOption }}
      />
    </div>
  );
}

3

Answers


  1. enter image description here
    just add position: relative on the option container, it will work

    Login or Signup to reply.
  2. you see when an option is selected and is being shown in the input, it is a layer underneath the input, thus, despite the fact that you are seeing the option there, when you click on it, you are not actually clicking on that, you are clicking on the select input causing the options dropdown to open.

    Login or Signup to reply.
  3. Issue number one: you have a react-select input overlayed your component, hence you click it instead of your single value component:

    devtools cannot lie

    To address that, you need to add z-index:

    const singleValueStyles = {
      singleValue: (styles) => ({ ...styles, "z-index": 2 }),
    };
    ...
    
    <Select
      className="dropdown"
      options={option}
      styles={singleValueStyles} // 👈
    ...
    
    

    After that, the button works well, however, we still get the dropdown opened. That’s because react-select uses onMouseDown rather that onClick. The easiest way to fix it is to use onMouseDown too:

    <button onMouseDown={handleEdit}>Edit</button>
    

    If you want to keep onClick, just add another handler for onMouseDown that only stops propagation.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search