TransWikia.com

Avoid multiple events on a dropdown: ReactJS

Stack Overflow Asked by li97 on February 17, 2021

I am trying to handle a tree inside of a checkbox. I am using onClick, onClose and onOpen for achieving opening of dropdown. But somehow onclick and onclose when clicked on semantic-ui-react. Can someone help me how to achieve this?

On click of dropdown it should open the dropdown and then toggle it, whenever tree changes are made it should be open.

https://codesandbox.io/s/semantic-ui-react-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>
    );
  }
}

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

2 Answers

If I understand it correctly you're having issue with dropdown not closing, I see in your code you're setting open to true in onClose.

onClose = e => {
    console.log("on close");
    this.setState({ open: false }); // this is `true` in your code
  };

As a further suggestion, use callback function in setState when you're using the existing state to modify the state.

// this.setState({ open: !this.state.open }); don't use this
this.setState((prevState)=>{
  return {
    open: !prevState.open,
  };
});

Correct answer by vatz88 on February 17, 2021

Your OnClick method changes state.open everytime element is clicked - even when u click inner element. That's why your dropdown is closed.

--

I think this is what you want, although I don't think this is the most elegant solution:

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(e.target)
    ///if(e.target.role==="listbox"){
      console.log("on close");
      this.setState({ open: false }); // this is `true` in your code  
    //}
};
  onOpen = e => {
    console.log("on open");
    this.setState({ open: true });
  };
  
  onChange = e => {
    console.log("on change");
    this.setState({ open: true });
  };*/
  onClick = e => {
    if(e.target.id==="dropdown" || e.target.className==="text" || e.target.className==="dropdown icon"){
      this.setState({ open: !this.state.open });
    }
    console.log("on click");
  };

  render() {
    return (
      <div>
        <Dropdown
          id="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>

        {/* <CheckboxTree
          nodes={nodes}
          checked={this.state.checked}
          expanded={this.state.expanded}
          onCheck={checked => this.setState({ checked })}
          onExpand={expanded => this.setState({ expanded })}
        /> */}
      </div>
    );
  }
}

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

Answered by raflab on February 17, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP