【问题标题】:How to render a component onClick with a button in another component?如何使用另一个组件中的按钮呈现组件 onClick?
【发布时间】:2020-09-16 00:29:45
【问题描述】:

我正在尝试使用组件内的“编辑”按钮来呈现组件。我决定在我的代码中使用条件渲染,但我似乎无法让它正常工作。有人对我如何实现这个结果有任何想法吗?我觉得我快要突破了,但我不知道我错过了什么。

ClientTable.js

import React, { Component } from "react";
import { Table, Container, Button } from "reactstrap";
import { connect } from "react-redux";
import {
  getClients,
  addClient,
  deleteClient,
  setClientToEdit,
} from "../actions/clientActions";
import PropTypes from "prop-types";
import ClientEditModal from "./ClientEditModal";

class ClientTable extends Component {
  state = {
    isOpen: false,
  };

  componentDidMount() {
    this.props.getClients();
  }

  openEditModal = () => {
    if (this.state.isOpen === false) {
      return <ClientEditModal />;
    } else {
      return null;
    }
  };

  onDeleteClick = (id) => {
    this.props.deleteClient(id);
  };

  renderClient = (clients, _id) => {
    return (
      <tr key={_id} timeout={500} classNames="fade">
        <td>
          <Button
            className="remove-btn"
            color="danger"
            size="sm"
            onClick={() => this.onDeleteClick(clients._id)}
          >
            &times;
          </Button>

          <Button
            style={{ marginLeft: ".2rem" }}
            className="add-btn"
            outline
            color="warning"
            size="sm"
            onClick={this.openEditModal}
          >
            Edit
          </Button>

          <Button
            style={{ marginLeft: ".3rem" }}
            className="detail-btn"
            outline
            color="info"
            size="sm"
            onClick={this.toggleDetails}
          >
            Details
          </Button>
        </td>
        <td>{clients.name}</td>
        <td>{clients.email}</td>
        <td>{clients.number}</td>
      </tr>
    );
  };

  render() {
    const { clients } = this.props.client;
    return (
      <Container id="listContainer">
        <Table
          id="listTable"
          className="table-striped table-bordered table-hover"
          dark
        >
          <tr class="listRow">
            <thead id="tableHeader">
              <tr>
                <th id="listActions">Actions</th>
                <th id="listName">Name</th>
                <th id="listEmail">Email</th>
                <th id="listNumber">Number</th>
              </tr>
            </thead>
            <tbody class="listRow">{clients.map(this.renderClient)}</tbody>
          </tr>
        </Table>
      </Container>
    );
  }
}

ClientTable.propTypes = {
  getClients: PropTypes.func.isRequired,
  client: PropTypes.object.isRequired,
};

const mapStateToProps = (state) => ({
  client: state.client,
});

export default connect(mapStateToProps, {
  getClients,
  deleteClient,
  addClient,
  setClientToEdit,
})(ClientTable);

ClientEditModal.js

import React, { Component } from "react";
import {
  Button,
  Modal,
  ModalHeader,
  ModalBody,
  Form,
  FormGroup,
  Label,
  Input,
} from "reactstrap";
import { connect } from "react-redux";
import { editClient } from "../actions/clientActions";
import PropTypes from "prop-types";

class ClientEditModal extends Component {
  state = {
    modal: false,
  };

  componentDidMount() {
    this.props.editClient();
  }

  toggle = () => {
    this.setState({
      modal: !this.state.modal,
    });
  };

  onChange = (e) => {
    this.setState({ [e.target.name]: e.target.value });
  };

  onSubmit = (e) => {
    e.preventDefault();

    // Close modal
    this.toggle();
  };

  render() {
    const { clients } = this.props.client;
    return (
      // Split button into separate component
      <div>
        <Modal isOpen={this.state.modal} toggle={this.toggle}>
          <ModalHeader toggle={this.toggle}> Edit</ModalHeader>

          <ModalBody>
            <Form onSubmit={this.onSubmit}>
              <FormGroup>
                <Label for="name"> Name </Label>
                <Input
                  type="text"
                  name="name"
                  id="client"
                  value={clients.name}
                  onChange={this.onChange}
                ></Input>
                <Label for="email"> Email </Label>
                <Input
                  type="text"
                  name="email"
                  id="client"
                  value={clients.email}
                  onChange={this.onChange}
                ></Input>
                <Label for="number"> Number </Label>
                <Input
                  type="text"
                  name="number"
                  id="number"
                  value={clients.number}
                  onChange={this.onChange}
                ></Input>
                <Button color="dark" style={{ marginTop: "2rem" }} block>
                  Submit Client Edit
                </Button>
              </FormGroup>
            </Form>
          </ModalBody>
        </Modal>
      </div>
    );
  }
}

ClientEditModal.propTypes = {
  editClient: PropTypes.func.isRequired,
  client: PropTypes.object.isRequired,
};

const mapStateToProps = (state) => ({
  client: state.client,
});

export default connect(mapStateToProps, { editClient })(ClientEditModal);

【问题讨论】:

  • 你能解释一下你的代码没有什么吗?你能谈谈错误吗?
  • 没有错误。当我单击“编辑”按钮时,它就不起作用了。
  • 你能安排一个codesandbox.io吗?
  • this.setState({ [e.target.name]: e.target.value });。这是什么意思?

标签: javascript reactjs redux conditional-rendering


【解决方案1】:

onClick 无法返回组件,这没有意义。

在 onClick 你应该设置状态。在渲染中你需要检查状态并渲染组件

例如:

{this.state.isOpen ? <ClientEditModal /> : null}

您的openEditModal 函数将如下所示

openEditModal = () => {
    if (this.state.isOpen === false) {
      this.setState({isOpen: true})
    } 
  };

您的 clientTable.jsx 将是

import React, { Component } from "react";
import { Table, Container, Button } from "reactstrap";
import { connect } from "react-redux";
import {
  getClients,
  addClient,
  deleteClient,
  setClientToEdit,
} from "../actions/clientActions";
import PropTypes from "prop-types";
import ClientEditModal from "./ClientEditModal";

class ClientTable extends Component {
  state = {
    isOpen: false,
  };

  componentDidMount() {
    this.props.getClients();
  }

  openEditModal = () => {
    if (this.state.isOpen === false) {
      this.setState({isOpen: true})
    } 
  };

  onDeleteClick = (id) => {
    this.props.deleteClient(id);
  };

  renderClient = (clients, _id) => {
    return (
      <tr key={_id} timeout={500} classNames="fade">
        <td>
          <Button
            className="remove-btn"
            color="danger"
            size="sm"
            onClick={() => this.onDeleteClick(clients._id)}
          >
            &times;
          </Button>

          <Button
            style={{ marginLeft: ".2rem" }}
            className="add-btn"
            outline
            color="warning"
            size="sm"
            onClick={this.openEditModal}
          >
            Edit
          </Button>

          <Button
            style={{ marginLeft: ".3rem" }}
            className="detail-btn"
            outline
            color="info"
            size="sm"
            onClick={this.toggleDetails}
          >
            Details
          </Button>
        </td>
        <td>{clients.name}</td>
        <td>{clients.email}</td>
        <td>{clients.number}</td>
      </tr>
    );
  };

  render() {
    const { clients } = this.props.client;
    return (
      <Container id="listContainer">
        {this.state.isOpen ? <ClientEditModal /> : null };
        <Table
          id="listTable"
          className="table-striped table-bordered table-hover"
          dark
        >
          <tr class="listRow">
            <thead id="tableHeader">
              <tr>
                <th id="listActions">Actions</th>
                <th id="listName">Name</th>
                <th id="listEmail">Email</th>
                <th id="listNumber">Number</th>
              </tr>
            </thead>
            <tbody class="listRow">{clients.map(this.renderClient)}</tbody>
          </tr>
        </Table>
      </Container>
    );
  }
}

ClientTable.propTypes = {
  getClients: PropTypes.func.isRequired,
  client: PropTypes.object.isRequired,
};

const mapStateToProps = (state) => ({
  client: state.client,
});

export default connect(mapStateToProps, {
  getClients,
  deleteClient,
  addClient,
  setClientToEdit,
})(ClientTable);

【讨论】:

  • 我这样做了,但仍然无法正常工作。在要渲染的所需组件中我有什么需要更改的吗
  • 也许我应该在我的 App.js 中添加一些东西?
  • 检查this.state.modal是否为真。设置为 true 进行测试。
猜你喜欢
  • 1970-01-01
  • 2020-08-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-27
  • 1970-01-01
  • 2018-01-08
  • 2017-01-12
相关资源
最近更新 更多