Search code examples
javascriptreactjseventssemantic-uisemantic-ui-react

Multiple events gets triggered on a semantic dropdown


I am trying to achieve the following behaviour. On click of a dropdown a tree should get displayed as an option, and whatever operation on the tree, should keep the dropdown open. It should only get closed whenever the dropdown is clicked again and also on outer click.I am using onClick, onClose and onOpen handlers. But somehow onclick and onclose are conflicting. Can someone help me how to achieve this?

Sandbox: https://codesandbox.io/s/semantic-ui-react-so-yzemk?file=/index.js

import React from "react";
import { render } from "react-dom";
import { Dropdown } from "semantic-ui-react";
import CheckboxTree from "react-checkbox-tree";
import "react-checkbox-tree/lib/react-checkbox-tree.css";
const nodes = [
  {
    value: "mars",
    label: "Mars",
    children: [
      { value: "phobos", label: "Phobos" },
      { value: "deimos", label: "Deimos" }
    ]
  }
];

class App extends React.Component {
  state = {
    checked: [],
    expanded: [],
    options: [],
    open: false
  };

  onClose = e => {
    console.log("on close");
    this.setState({ open: true });
  };

  onOpen = e => {
    console.log("on open");
    this.setState({ open: true });
  };

  onChange = e => {
    console.log("on change");
    e.stopPropagation();
    this.setState({ open: true });
  };

  onClick = e => {
    console.log("on click");
    e.stopPropagation();
    this.setState({ open: !this.state.open });
  };

  render() {
    return (
      <div>
        <Dropdown
          className="icon"
          selection
          options={this.state.options}
          text="Select"
          open={this.state.open}
          onClose={this.onClose}
          onOpen={this.onOpen}
          onChange={this.onChange}
          onClick={this.onClick}
        >
          <Dropdown.Menu>
            <Dropdown.Item>
              <CheckboxTree
                nodes={nodes}
                checked={this.state.checked}
                expanded={this.state.expanded}
                onCheck={checked =>
                  this.setState({ checked }, () => {
                    console.log(this.state.checked);
                  })
                }
                onExpand={expanded => this.setState({ expanded })}
              />
            </Dropdown.Item>
          </Dropdown.Menu>
        </Dropdown>
      </div>
    );
  }
}

Solution

  • You have a bug in the onClose function. change it to this:

    onClose = e => {
        console.log("on close");
        this.setState({ open: false });
      };
    

    ----EDIT----

    After reading a bit I figured out the problem: First - you don't need to implement all these onClick, onOpen, onClose functions. You simply need to add stopPropagation() on the Dropdown.Item. Check out this code - let me know if that works for you:

    import React from "react";
    import { render } from "react-dom";
    import { Dropdown } from "semantic-ui-react";
    import CheckboxTree from "react-checkbox-tree";
    import "react-checkbox-tree/lib/react-checkbox-tree.css";
    const nodes = [
      {
        value: "mars",
        label: "Mars",
        children: [
          { value: "phobos", label: "Phobos" },
          { value: "deimos", label: "Deimos" }
        ]
      }
    ];
    
    class App extends React.Component {
      state = {
        checked: [],
        expanded: [],
        options: [],
        open: false
      };
    
      render() {
        return (
          <div>
            <Dropdown
              className="icon"
              selection
              text="Select"
            >
              <Dropdown.Menu>
                <Dropdown.Item onClick={(e) => e.stopPropagation()}>
                  <CheckboxTree
                    nodes={nodes}
                    checked={this.state.checked}
                    expanded={this.state.expanded}
                    onCheck={checked =>
                      this.setState({ checked }, () => {
                        console.log(this.state.checked);
                      })
                    }
                    onExpand={expanded => this.setState({ expanded })}
                  />
                </Dropdown.Item>
              </Dropdown.Menu>
            </Dropdown>
          </div>
        );
      }
    }
    
    render(<App />, document.getElementById("root"));