reactjs下拉菜单关闭打开菜单

时间:2019-10-14 17:13:04

标签: reactjs drop-down-menu menu popup dropdown

我使用表格上的API传输数据。 对于每个记录,表上都有一个下拉菜单。 下拉式菜单。 但是下拉菜单不会关闭。 因此,当我单击桌子上的空白处时,下拉菜单不会关闭。

我希望关闭下拉菜单。

即如何设置切换状态。 你能帮忙吗?

<buttondropdown
isOpen = {this.state.table_dropdownMap.get (item.id)}
toggle = {this.table_dropdownToggle}

enter image description here

import React, { Component } from "react";
import withAuth from "../../components/helpers/withAuth";
import {
  Card,
  CardBody,
  CardHeader,
  Col,
  Row,
  Table,
  DropdownItem,
  DropdownMenu,
  DropdownToggle,
} from "reactstrap";
import { connect } from "react-redux";
import ButtonDropdown from "reactstrap/es/ButtonDropdown";


class CustomerDebt extends Component {
  constructor(props) {
    super(props);

    this.domain = `http://127.0.0.1:8000`;

    this.state = {
      top_dropdownOpen: false,
      table_dropdownOpen: false,
      table_dropdownMap: new Map(),

      modal: false,
      isLoaded: true,

      items: [],
      selectedItem:{ }
    };

    this.top_dropdownToggle = this.top_dropdownToggle.bind(this);
    this.table_dropdownToggle = this.table_dropdownToggle.bind(this);

    this.debtModalForm = this.debtModalForm.bind(this);
    this.handleChange = this.handleChange.bind(this);

    this.handleSubmitUpdate = this.handleSubmitUpdate.bind(this);
    this.handleSubmitCreate = this.handleSubmitCreate.bind(this);
  }

  //Customer debts unmounts - refresh problem
  abortController = new AbortController();
  componentWillUnmount = () => {
    this.abortController.abort();
  };


  //Get customer debts
  async componentDidMount() {

    await fetch(
        `${this.domain}/api/debt/list?customer=` +
        this.props.customerInfo.customer.id,
        {
          headers: {
            Authorization: `Bearer ${localStorage.getItem("id_token")}`,
            "Content-Type": "application/json"
          }
        }
    )
        .then(res => {
          if (res.ok) {
            return res.json();
          } else {
            return res.json().then(err => Promise.reject(err));
          }
        })
        .then(json => {
          this.setState({
            items: json
          });
          this.abortController.abort();
          // console.log(json)
        })
        .catch(error => {
          //console.log('request failed:', error);
          return error;
        });
  }


  debtModalForm (value) {
    console.log( value);

    if (value === "newRecord") {
      this.setState( prevState =>({
        modal: !prevState.modal,
      }))
    } else {

      console.log(value);

      this.setState(prevState => ({
        modal: !prevState.modal,

        selectedItem: value,

        user: value.user,
        customer: value.customer,
        debtKey: value.debtKey,
        createduserKey: value.createduserKey,
        totalDebt: value.totalDebt,
        receivedAmount: value.receivedAmount,
        description: value.description,
        paymentDate: value.paymentDate
      }));
    }

  }


  //text handleChange
  handleChange(e) {
    this.setState({
      [e.target.name]: e.target.value
    });
  }


  //dropdown toggle menu
  top_dropdownToggle = () => {
    this.setState(prevState => ({
      top_dropdownOpen: !prevState.top_dropdownOpen,
    }));
  };

  //table dropdown menü
  table_dropdownToggle ()  {
    this.setState(prevState => ({
      table_dropdownOpenMap: !prevState.table_dropdownOpenMap,
    }));

    console.log(this.state.table_dropdownOpenMap)
  };



render() {
    const { isLoaded, items } = this.state;
    if (!isLoaded) {
      return <div>Loading...</div>;
    } else {
      return (
          <div className={"animated fadeIn container-fluid"}>
            <Row>
              <Col>
                <Card>
                  <CardHeader>
                    <i className="fa fa-align-justify" /> Customer Debt
                  </CardHeader>
                  <CardBody>
                    <Table hover bordered striped responsive size="sm">
                      <thead>
                      <tr>
                        <th width={"10"} />
                        <th width={"15"}>No</th>
                        <th style={{ display: "none" }}>User</th>
                        <th style={{ display: "none" }}>Key</th>
                        <th style={{ display: "none" }}>CreatedUserKey</th>
                        <th width={"40"}>Total Debt</th>
                        <th width={"40"}>Received Amount</th>
                        <th scope={"row"}>Description</th>
                        <th width={"20"}>Payment Date</th>
                      </tr>
                      </thead>
                      <tbody>

                      {items.map(item => {
                        return (
                            <tr key={item.id}>

                              <td >
                                <ButtonDropdown
                                    isOpen={  this.state.table_dropdownMap.get(item.id) }
                                    toggle={  this.table_dropdownToggle }

                                    onClick={ () => {
                                      let updatedMap = new Map(this.table_dropdownMap);
                                      updatedMap.set(item.id, !updatedMap.get(item.id));
                                      this.setState({ table_dropdownMap: updatedMap });

                                      console.log("clicked : "+ item.id)
                                    }}
                                >
                                  <DropdownToggle caret >
                                    Process
                                  </DropdownToggle>
                                  <DropdownMenu>
                                    <DropdownItem >New Record</DropdownItem>
                                    <DropdownItem >Print All</DropdownItem>
                                    <DropdownItem>Action 3</DropdownItem>
                                    <DropdownItem divider />
                                    <DropdownItem>Another Action</DropdownItem>
                                  </DropdownMenu>
                                </ButtonDropdown>
                              </td>
                              <td>{item.id}</td>
                              <td style={{ display: "none" }}>{item.user}</td>
                              <td style={{ display: "none" }}>{item.debtKey}</td>
                              <td style={{ display: "none" }}> {item.createduserKey} </td>
                              <td>{item.totalDebt}</td>
                              <td>{item.receivedAmount}</td>
                              <td>{item.description}</td>
                              <td>{new Date(item.paymentDate).toLocaleString()}</td>
                            </tr>
                        )
                      })}
                      </tbody>
                    </Table>
                  </CardBody>
                </Card>
              </Col>
            </Row>
          </div>
      );
    }
  }
}
const mapStateToProps = state => {
  return state;
};
export default connect(mapStateToProps)(withAuth(CustomerDebt));

1 个答案:

答案 0 :(得分:0)

您应该为按钮创建一个组件,该组件具有对toggle属性的自包含状态,而不是尝试创建存储每个按钮的每个按钮切换状态的对象。因此,创建一个这样的DropdownButton组件:

import React from 'react';
import { Dropdown, DropdownToggle, DropdownMenu, DropdownItem } from 'reactstrap';

export default class DropdownButton extends React.Component {
  constructor(props) {
    super(props);

    this.toggle = this.toggle.bind(this);
    this.state = {
      dropdownOpen: false
  };
}

toggle() {
  this.setState(prevState => ({
    dropdownOpen: !prevState.dropdownOpen
  }));
}

render() {
 return (
  <Dropdown isOpen={this.state.dropdownOpen} toggle={this.toggle}>
    <DropdownToggle caret>
      Dropdown
    </DropdownToggle>
    <DropdownMenu>
       <DropdownItem >New Record</DropdownItem>
        <DropdownItem >Print All</DropdownItem>
        <DropdownItem>Action 3</DropdownItem>
        <DropdownItem divider />
        <DropdownItem>Another Action</DropdownItem>
       </DropdownMenu>
     </Dropdown>
   );
 }
} 

然后,您可以将DropdownButton用作子组件:

<DropdownButton />

它将具有独立的切换状态。