Replace Second Modal with First Modal

Tags: , , ,



First Check my react-bootstrap codes:

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      show: false
    };
  }

  handleShow = (e) => {
    this.setState({ show: true });
  };

  handleClose = (e) => {
    this.setState({ show: false });
  };

  render() {
    return (
      <div className="App">
        <button onClick={this.handleShow}>Open Modal</button>
        <Modal
          size="lg"
          centered={true}
          show={this.state.show}
          onHide={this.handleClose}
          aria-labelledby="md-modal"
        >
          <Modal.Header>
            First Modal
            <button
              type="button"
              className="close"
              onClick={this.handleClose}
            >
             X
            </button>
          </Modal.Header>
          <Modal.Body>
            Please <Content clicked={this.handleClose} /> to show New Content
          </Modal.Body>
        </Modal>
      </div>
    );
  }
}

class Content extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      show: false
    };
  }

  handleShow = (e) => {
    this.props.clicked();
    this.setState({ show: true });
  };

  handleClose = (e) => {
    this.setState({ show: false });
  };
  render() {
    return (
      <>
        <button onClick={this.handleShow}>Click Here</button>
        <Modal
          size="lg"
          centered={true}
          show={this.state.show}
          onHide={this.handleClose}
          aria-labelledby="md-modal"
        >
          <Modal.Header>
            Second Modal
            <button
              type="button"
              className="close"
              onClick={this.handleClose}
            >
              X
            </button>
          </Modal.Header>
          <Modal.Body>New Content</Modal.Body>
        </Modal>
      </>
    );
  }
}

I need to show second modal then hide first modal after clicked on the button on first modal.

You can see demo here: https://codesandbox.io/s/xenodochial-joliot-jl3qe

the problem is the both of modal was hide when click on the button on first modal.

maybe i need to use redux in this case ?

Answer

so we need to track the statuses for the 2 modals… the only difference being that since modal-2 can be triggered from inside modal-1, we need to make sure that we close modal-1 when we are displaying modal-2;

I showed the statuses on the screen so that it becomes easier to track and understand;

following is the relevant code:

import React, { useState, useEffect } from "react";
import { Modal } from "react-bootstrap";
import "./styles.css";

const Modal1 = ({
  modalState,
  modalHeading,
  toggleModalOne,
  openTwoAndCloseOne
}) => {
  const [modalOpen, setModalOpen] = useState(modalState);

  useEffect(() => {
    setModalOpen(modalState);
  }, [modalState]);

  return (
    <Modal
      size="lg"
      centered={true}
      show={modalOpen}
      onHide={toggleModalOne}
      aria-labelledby="md-modal"
    >
      <Modal.Header>
        {modalHeading}
        <button type="button" className="close p-2" onClick={toggleModalOne}>
          close <i className={"mdi mdi-close"} />
        </button>
      </Modal.Header>
      <Modal.Body className="p-0">
        New Content
        <button type="button" onClick={openTwoAndCloseOne}>
          close first & open second
        </button>
      </Modal.Body>
    </Modal>
  );
};

const Modal2 = ({ modalState, modalHeading, toggleModalTwo }) => {
  const [modalOpen, setModalOpen] = useState(modalState);

  useEffect(() => {
    setModalOpen(modalState);
  }, [modalState]);

  return (
    <Modal
      size="lg"
      centered={true}
      show={modalOpen}
      onHide={toggleModalTwo}
      aria-labelledby="md-modal"
    >
      <Modal.Header>
        {modalHeading}
        <button type="button" className="close p-2" onClick={toggleModalTwo}>
          close <i className={"mdi mdi-close"} />
        </button>
      </Modal.Header>
      <Modal.Body className="p-0">
        ths is the Second modal and its New Content
      </Modal.Body>
    </Modal>
  );
};

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      show: false,
      showSecond: false
    };
  }

  toggleModalOne = (e) => {
    this.setState({ show: !this.state.show });
  };

  toggleModalTwo = (e) => {
    this.setState({ showSecond: !this.state.showSecond });
  };

  openTwoAndCloseOne = (e) => {
    this.setState({ showSecond: !this.state.showSecond });
    if (this.state.show) this.setState({ show: false });
  };

  render() {
    return (
      <div className="App">
        1st modal current show status: {this.state.show.toString()}
        <br />
        2nd modal current show status: {this.state.showSecond.toString()}
        <br />
        <button type="button" onClick={this.toggleModalOne}>
          change Modal1 status to {(!this.state.show).toString()}
        </button>
        <Modal1
          modalHeading={"this is modal heading for the first mofal"}
          modalState={this.state.show}
          toggleModalOne={this.toggleModalOne}
          openTwoAndCloseOne={this.openTwoAndCloseOne}
        />
        {/* 
        <button type="button" onClick={this.toggleModalTwo}>
          change Modal2 status to {(!this.state.showSecond).toString()}
        </button> */}
        <Modal2
          modalHeading={"this is modal heading for the second modal..."}
          modalState={this.state.showSecond}
          toggleModalTwo={this.toggleModalTwo}
        />
      </div>
    );
  }
}

complete working example forked off your code-sandbox here



Source: stackoverflow