【问题标题】:Prevent multiple on-click events from firing: ReactJS防止触发多个点击事件:ReactJS
【发布时间】:2019-07-30 06:26:55
【问题描述】:

我有一种情况,我有多个在列标题上触发的点击事件。将有一个过滤器下拉事件和另一个排序事件。有一个过滤器图标 ,单击将显示哪些列过滤器选项。在点击标题时,也应该进行排序。

现在,每当我单击过滤器图标时,两个处理程序都会被触发。有人可以帮我弄这个吗。

点击过滤器图标时,只有过滤器处理程序应该触发

我们将不胜感激。

沙盒:https://codesandbox.io/s/relaxed-feather-xrpkp

家长

import * as React from "react";
import { render } from "react-dom";
import ReactTable from "react-table";
import "./styles.css";
import "react-table/react-table.css";
import Child from "./Child";
interface IState {
  data: {}[];
  columns: {}[];
}

interface IProps {}

export default class App extends React.Component<IProps, IState> {
  constructor(props: any) {
    super(props);
    this.state = {
      data: [
        { firstName: "Jack", status: "Submitted", age: "14" },
        { firstName: "Simon", status: "Pending", age: "15" },
        { firstName: "Pete", status: "Approved", age: "17" }
      ],
      columns: []
    };
  }

  handleColumnFilter = (value: any) => {
    console.log(value);
  };

  sortHandler = () => {
    console.log("sort handler");
  };

  componentDidMount() {
    let columns = [
      {
        Header: () => (
          <div onClick={this.sortHandler}>
            <div style={{ position: "absolute", marginLeft: "10px" }}>
              <Child handleFilter={this.handleColumnFilter} />
            </div>
            <span>First Name</span>
          </div>
        ),
        accessor: "firstName",
        sortable: false,
        show: true,
        displayValue: " First Name"
      },
      {
        Header: () => (
          <div onClick={this.sortHandler}>
            <span>Status</span>
          </div>
        ),
        accessor: "status",
        sortable: false
      }
    ];
    this.setState({ columns });
  }

  render() {
    const { data, columns } = this.state;
    return (
      <div>
        <ReactTable
          data={data}
          columns={columns}
          defaultPageSize={10}
          className="-striped -highlight"
        />
      </div>
    );
  }
}

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

过滤器组件

import * as React from "react";
import { Icon } from "semantic-ui-react";
import "./styles.css";
interface IProps {
  handleFilter(val1: any): void;
}
interface IState {
  showList: boolean;
}
export default class Child extends React.Component<IProps, IState> {
  constructor(props: any) {
    super(props);
    this.state = {
      showList: false
    };
  }

  toggleList = () => {
    console.log("filter handler");
    this.setState(prevState => ({ showList: !prevState.showList }));
  };

  render() {
    let { showList } = this.state;
    let visibleFlag: string;
    if (showList === true) visibleFlag = "visible";
    else visibleFlag = "";
    return (
      <div>
        <div style={{ position: "absolute" }}>
          <div
            className={"ui scrolling dropdown column-settings " + visibleFlag}
          >
            <Icon className="filter" onClick={this.toggleList} />
          </div>
        </div>
      </div>
    );
  }
}


【问题讨论】:

    标签: javascript reactjs ecmascript-6 dom-events setstate


    【解决方案1】:

    您只需要event.stopPropagation()。这会将事件隔离到仅这个特定的执行块。所以现在当你点击过滤器图标时,它只会触发指定的事件处理程序。

      toggleList = (event) => {
        event.stopPropgation()
        console.log("filter handler");
        this.setState(prevState => ({ showList: !prevState.showList }));
      };
    

    您还需要在这里使用它:

      handleValueChange = (event: React.FormEvent<HTMLInputElement>, data: any) => {
        event.stopPropagation()
        let updated: any;
        if (data.checked) {
          updated = [...this.state.selected, data.name];
        } else {
          updated = this.state.selected.filter(v => v !== data.name);
        }
        this.setState({ selected: updated });
      };
    

    这里:

     passSelectionToParent = (event: any) => {
        event.preventDefault();
        event.stopPropagation()
        this.props.handleFilter(this.props.name, this.state.selected);
      };
    

    从字面上看,只要您有父标记的点击事件,并且它的子标记也有点击事件,您可以使用event.stopPropagation() 来阻止父点击事件触发。

    这里是沙盒:https://codesandbox.io/s/elated-gauss-wgf3t

    【讨论】:

    • @vjr 如果你把它放在toggleList() 上,那么过滤器处理程序就会被触发。似乎在我的沙箱中工作正常:codesandbox.io/s/strange-cherry-tu6yr
    • @vjr 我不知道是不是只有我一个人。但是编译这些沙盒的速度慢得离谱。
    • @vjr 不客气。我也添加了指向沙盒的链接,但看起来您已经更新了代码:)
    • @vjr 是的!刚刚发布了你的新作品的答案
    • @vjr 哦,是的!我已对其进行了编辑,因为我不确定您是否要包含 :)。最初没有否定哈哈。对不起,我很困惑。我会改回来的。
    猜你喜欢
    • 1970-01-01
    • 2015-04-28
    • 2016-06-03
    • 1970-01-01
    • 1970-01-01
    • 2012-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多