按钮onClick事件未更新组件状态

时间:2019-05-13 19:11:50

标签: reactjs react-bootstrap

我正在使用React-bootstrap来显示删除确认模式

这是我的确认模型

import React from "react";
import PropTypes from "prop-types";
import Button from "@material-ui/core/Button";
import Modal from "react-bootstrap/lib/Modal";
import "./ConfirmationModal.scss";

class ConfirmationModal extends React.PureComponent {
  render() {
    return (
      <Modal
        {...this.props}
        size="md"
        aria-labelledby="contained-modal-title-vcenter"
        centered
        className="confirmation-modal"
      >
        <Modal.Header closeButton />
        <Modal.Body>
          <h4>Are you sure you want to delete?</h4>
          <p>{`You are about to delete ${this.props.deleteItem}`}</p>
        </Modal.Body>
        <Modal.Footer>
          <Button className="cancel-btn btn" onClick={this.props.onHide}>
            {"No, Cancel"}
          </Button>
          <Button className="delete-btn btn" onClick={this.props.onDelete}>
            {"Yes, Delete"}
          </Button>
        </Modal.Footer>
      </Modal>
    );
  }
}

ConfirmationModal.propTypes = {
  onClick: PropTypes.func,
  onDelete: PropTypes.func,
  deleteItem: PropTypes.string
};

ConfirmationModal.defaultProps = {
  onClick: () => {},
  onDelete: () => {},
  deleteItem: null
};

export { ConfirmationModal as default };

这是被调用的页面(最终,我将向GridCommandCell delete函数添加该代码段,但为简单起见,我创建了Button

import React from "react";
import PropTypes from "prop-types";
import Button from "@material-ui/core/Button";
import { Grid, GridColumn as Column } from "@progress/kendo-react-grid";
import GridLoader from "../../../common/utils/grid-loader";
import GridCommandCell from "../../../common/grid-command-cell";

import ConfirmationModal from "../../../common/confirmation-modal";
import "./UserGrid.scss";

class UserGrid extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      modalShow: false,
      gridData: { data: [], total: 0 },
      dataState: {
        take: 10,
        skip: 0,
        filter: [],
        sort: [
          {
            field: "Id",
            dir: "desc"
          }
        ]
      }
    };

    this.grid = React.createRef();
  }

  dataRecieved = gridData => {
    this.setState(prevState => ({
      ...prevState,
      gridData
    }));
  };

  dataStateChanged = e => {
    const index = e.data.filter.filters.findIndex(x => x.field === "Role.Name");

    if (index >= 0) e.data.filter.filters[index].ignoreCase = true;

    this.setState(prevState => ({
      ...prevState,
      dataState: e.data
    }));
  };

  refresh = () => {
    this.grid.refresh();
  };

  render() {
    const result = (
      <div className="gridContent-grid">
        <Grid
          id="user-grid"
          filterable
          sortable
          pageable={{
            buttonCount: 5,
            info: false,
            type: "numeric",
            pageSizes: false,
            previousNext: false
          }}
          {...this.state.dataState}
          {...this.state.gridData}
          onDataStateChange={this.dataStateChanged}
        >
          <Column field="Id" filter="numeric" title="Id" />
          <Column field="FirstName" title="First Name" />
          <Column field="LastName" title="Last Name" />
          <Column field="Role.Name" title="Role" />
          <Column
            className="command-btn"
            width="100%"
            cell={props => {
              const commandCell = (
                <GridCommandCell
                  onEdit={() => this.props.onEdit(props.dataItem.Id)}
                  // I need to set the onDelete to on click, activate modal
                  // onDelete={() => this.props.onDelete(props.dataItem.Id)}
                  onClick={() => this.setState({ modalShow: true })}
                />
              );
              return commandCell;
            }}
            filterable={false}
            sortable={false}
          />
          <ConfirmationModal
            show={this.state.modalShow}
            onHide={() => this.setState({ modalShow: false })}
            // onDelete={() => this.props.onDelete(dataItem.Id)}
            // deleteItem={`${dataItem.FirstName} ${dataItem.LastName}`}
          />
        </Grid>
        <GridLoader
          url="/odata/users?$select=Id, FirstName, LastName&$expand=Role&count=true&"
          dataState={this.state.dataState}
          onDataRecieved={this.dataRecieved}
          ref={grid => {
            this.grid = grid;
          }}
        />
        <Button
          variant="contained"
          className="delete-btn btn"
          type="button"
          onClick={() => {
            console.log(this.state);
            () => this.setState({ modalShow: true });
            console.log(this.state);
          }}
        >
          <span className="button-label">Delete modal</span>
        </Button>
      </div>
    );

    return result;
  }
}

UserGrid.propTypes = {
  onEdit: PropTypes.func,
  onDelete: PropTypes.func
};

UserGrid.defaultProps = {
  onEdit: () => {},
  onDelete: () => {}
};

export { UserGrid as default };

我正在尝试通过记录在in React-bootstrap Modals上的onClick事件来更新模态的状态

通过此按钮

       <Button
          variant="contained"
          className="delete-btn btn"
          type="button"
          onClick={() => {
            console.log(this.state);
            () => this.setState({ modalShow: true });
            console.log(this.state);
          }}
        >
          <span className="button-label">Delete modal</span>
        </Button>

但是,我的console.log语句都返回modalShow: false

我无法弄清楚为什么onClick事件后状态不会更新。

请协助。谢谢!

1 个答案:

答案 0 :(得分:1)

设置状态是异步的。

  

setState()不会立即使this.state突变,而是创建一个挂起的状态转换。调用此方法后访问this.state可能会返回现有值。无法保证对setState调用的同步操作,并且可能会批量调用以提高性能。

这样做

this.setState({ modalShow: true });
// might give old values, as state hasn't been set yet.
console.log(this.state);

您的状态不会随着您进行的() => this.setState({ modalShow: true });更新而更改。

console.log(this.state);
this.setState({ modalShow: true }, console.log(this.state)); // pass setstate a callback which will be executed after the state is set.

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.0/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.21.1/babel.min.js"></script>
<div id="root"></div>

<script type="text/babel">

class App extends React.Component {
  constructor() {
    super();
    this.state = {
      name: 'React',
      modalShow: false
    };
  }

  render() {
    return (
      <div>
        <p onClick={() => {
          console.log(this.state);
          this.setState({ modalShow: true }, () => {
            console.log(this.state);
          });
          
        }}>
          Calling state with a callback
        </p>
        <p onClick={()=> {
          console.log(this.state);
          this.setState({ modalShow: true });
          console.log(this.state);
        }}>
        Priniting state after setting value
        </p>
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById('root'));
</script>