0

I'm trying to render component with an "Edit" button that is within the component. I decided to use conditional rendering in my code, but I can't seem to get it to work properly. Does anyone have any ideas on how I can achieve this result? I feel like I'm coming to a break through, but I don't know what I'm missing.

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);
4
  • can you explain what your code doesn't? can you talk about the error? Commented May 28, 2020 at 15:53
  • There is no error. When I click the "Edit" button it just doesn't work. Commented May 28, 2020 at 16:09
  • can you arrange a codesandbox.io? Commented May 29, 2020 at 7:22
  • this.setState({ [e.target.name]: e.target.value });. what does it means? Commented May 29, 2020 at 7:22

1 Answer 1

0

onClick cannot return a component, that doesn't make sense.

In onClick you should set the state. And in the render you need to check the state and render the component

eg:

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

and your openEditModal function will look like this

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

Your clientTable.jsx will be

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);
Sign up to request clarification or add additional context in comments.

3 Comments

I did this, but it's still not working. Is there anything I have to change in the desired component to be rendered
Maybe I should add something in my App.js?
Check whether this.state.modal is true. Set it as true to test.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.