Boostrap Modal React Hook

2.1k Views Asked by At

I am trying to learn React Hooks with a Bootstrap Modal example. I have the following Modal (from the react bootstrap website).

import React, { useState } from "react";
import {Button, Modal} from 'react-bootstrap';

function SimpleModal() {

const [show, setShow] = useState(false);

const handleClose = () => setShow(false);
const handleShow = () => setShow(true);

return (
  <>
    <Button variant="primary" onClick={handleShow}>
      Launch demo modal
    </Button>

    <Modal show={show} onHide={handleClose} animation={true}>
      <Modal.Header closeButton>
        <Modal.Title>Modal heading</Modal.Title>
      </Modal.Header>
      <Modal.Body>Woohoo, you're reading this text in a modal!</Modal.Body>
      <Modal.Footer>
        <Button variant="secondary" onClick={handleClose}>
          Close
        </Button>
        <Button variant="primary" onClick={handleClose}>
          Save Changes
        </Button>
      </Modal.Footer>
    </Modal>
  </>
);
}
export default SimpleModal;

Inside an axios response I want to show this Modal

 import React, { Component } from 'react';
 import axios from 'axios';

 import SimpleModal from "../components/SimpleModal"

 export default class CreateInnovation extends Component {


constructor(props) {
    super(props);
    this.onChangeOwnerName = this.onChangeOwnerName.bind(this);
    this.onChangeOwnerDepartment = this.onChangeOwnerDepartment.bind(this);
    this.onChangeOwnerWorkLocation = this.onChangeOwnerWorkLocation.bind(this);
    this.onSubmit = this.onSubmit.bind(this);

    this.state = {
        owner_name: '',
        owner_department: '',
        owner_work_location: ''
    }
}

onChangeOwnerName(e) {
    this.setState({
        owner_name: e.target.value
    });
}
onChangeOwnerDepartment(e) {
    this.setState({
        owner_department: e.target.value
    });
}
onChangeOwnerWorkLocation(e) {
    this.setState({
        owner_work_location: e.target.value
    });
}


onSubmit(e) {
    e.preventDefault();
    
    console.log(`Form submitted:`);
    console.log(`Owner Name: ${this.state.owner_name}`);
    console.log(`Owner Department: ${this.state.owner_department}`);
    console.log(`Owner Work Location: ${this.state.owner_work_location}`);

    const newInnovation = {
        owner_name: this.state.owner_name,
        owner_department: this.state.owner_department,
        owner_work_location: this.state.owner_work_location
    };

    axios.post('http://localhost:4000/innov8/create', newInnovation)
        .then(res => {
                if (res.status === 200) {
                    console.log(res.data);
                    <SimpleModal show={"true"} />
                }
            }
         );
    // Purge state
    this.setState({
        owner_name: '',
        owner_department: '',
        owner_work_location: ''
    })
}

render() {
    return (
        <div>
            <h1 id="heading" className='margin'>Innovation<span className="badge badge-primary margin">A3</span></h1>
            <h5 className='margin'>Your Details</h5>

            <form id='Innovationform' onSubmit={this.onSubmit}>
                <div className="container-fluid">
                    <div className="form-row">
                        <div className="col-sm ">
                            <input 
                                id="owner"
                                type="text" 
                                className="form-control" 
                                value={this.state.owner_name}
                                onChange={this.onChangeOwnerName}
                                maxLength="40" 
                                placeholder="Owner Name" 
                                required
                                />
                        </div>
                        <div className="col-sm">
                            <select id="department" className='form-control' value={this.state.owner_department} onChange={this.onChangeOwnerDepartment} required>
                                <option value="" disabled>Select Your Department</option>
                                <option value="acc">Accounts</option>
                                <option value="cat">Catering</option>
                                <option value="com">Commercial</option>
                                <option value="dig">Digitalisation &amp; Business Transformation</option>
                                <option value="dri">Drilling</option>
                                <option value="ele">Electrical</option>
                                <option value="eng">Engineering</option>
                                <option value="fac">Facilities</option>
                                <option value="fin">Finance</option>
                                <option value="hse">HSE</option>
                                <option value="hum">Human Resources</option>
                                <option value="inf">Information Technology</option>
                                <option value="mar">Marine</option> 
                                <option value="mec">Mechanical</option>                
                                <option value="ops">Operations</option>
                                <option value="pay">Payroll</option>                      
                                <option value="pro">Procurement</option>
                                <option value="sub">Subsea</option>
                                <option value="tec">Technical</option>
                                <option value="war">Warehouse</option>   
                                <option value="oth">Other</option>                                  
                            </select>
                        </div>  
                        <div className="col-sm ">
                            <select id="workplace" className='form-control' value={this.state.owner_work_location} onChange={this.onChangeOwnerWorkLocation} required>
                                    <option value="" disabled>Select Your Workplace</option>
                                    <option value="abe">Aberdeen</option>
                                    <option value="car">Stena Carron</option>
                                    <option value="don">Stena Don</option>
                                    <option value="dri">Stena DrillMAX</option>
                                    <option value="for">Stena Forth</option>
                                    <option value="ice">Stena IceMAX</option>
                                    <option value="spe">Stena Spey</option>
                                    <option value="oth">Other</option>
                                </select>
                        </div>
                    </div>                          
                </div>
                <div className="container">
                    <div className="form-row">
                        <div className="col text-center">
                            <button id="formSubmit" type="submit" className="btn btn-primary center-block buttonload">Submit Your Innovation!</button>
                        </div>
                    </div>
                </div>
            </form>
        </div>
    )
}
 }

My thinking is that I need to create the SimpleModal component and use the setShow hook to set "true". I have been searching for a few hours now & am struggling a tad. I have a button in the Modal function just now for testing, but I want to remove this button and only open the modal on success of the Axios response. Am I looking in the right direction?

2

There are 2 best solutions below

9
Sangam Rajpara On BEST ANSWER

Here is the solution You have to pass show in props to the model

Put this state into your I'm guessing createOwner component from which you shared onSubmit method

this.state= {
  show: false,
  owner_name: '',
  owner_department: '',
  owner_work_location: ''
}

Pass is down to the SimpleModal component in which you are rendering modal

Render modal in your create owner component.

<SimpleModal show={this.state.show} onClose={()=>{this.setState({show:false})}} />

In Your simpleModel File get it from props

import React, { useState } from 'react'
import { Button, Modal } from 'react-bootstrap'
function SimpleModal({ show, onClose }) {
return (
    <>
        <Modal show={show} onHide={onClose} animation={true}>
            <Modal.Header closeButton>
                <Modal.Title>Modal heading</Modal.Title>
            </Modal.Header>
            <Modal.Body>Woohoo, you're reading this text in a modal!</Modal.Body>
            <Modal.Footer>
                <Button variant="secondary" onClick={onClose}>
                    Close
                </Button>
                <Button variant="primary" onClick={onClose}>
                    Save Changes
                </Button>
            </Modal.Footer>
        </Modal>
    </>
)
}
export default SimpleModal
2
codemonkey On

Based on your post, I assume you don't actually need that button that pops the modal up. Instead you only want to render it based on that axios call. If the call is successfully (i.e. returns the 200 code), you want to show the modal.

To do that, I would, in fact, create a separate element with the modal code like you do, but I would control its state from your main class. See, you can't render something from outside of the render function, so in your axios request function all you can do is change a state, which will signal to the class that a state has changed and a re-render is in order. So what we will do is set a state variable called show_modal to true when the axios call is good. Then in the render function, render the Modal element. Here is a Sandbox for you, but I will include the code here for future reference:

import React, { useState, Component } from "react";
import Modal from "react-bootstrap/Modal";
import Button from "react-bootstrap/Button";
import "bootstrap/dist/css/bootstrap.css";
import axios from "axios";

function SimpleModal({ handleClose }) {
  return (
    <>
      <Modal show={true} onHide={handleClose} animation={true}>
        <Modal.Header closeButton>
          <Modal.Title>Modal heading</Modal.Title>
        </Modal.Header>
        <Modal.Body>Woohoo, you're reading this text in a modal!</Modal.Body>
        <Modal.Footer>
          <Button variant="secondary" onClick={handleClose}>
            Close
          </Button>
          <Button variant="primary" onClick={handleClose}>
            Save Changes
          </Button>
        </Modal.Footer>
      </Modal>
    </>
  );
}

export default class CreateInnovation extends Component {
  constructor(props) {
    super(props);

    this.state = {
      show_modal: false,
      owner_name: "",
      owner_department: "",
      owner_work_location: ""
    };
  }

  makeAxiosCall = () => {
    axios.post("https://httpstat.us/200", { somedata: "" }).then((res) => {
      if (res.status === 200) {
        console.log(res.data);
        this.setState({ show_modal: true });
      }
    });
  };

  handleModalClose = () => this.setState({ show_modal: false });

  render() {
    const { show_modal } = this.state;

    return (
      <div className="App">
        <h1>Hello CodeSandbox</h1>
        <h2>Start editing to see some magic happen!</h2>

        <button onClick={this.makeAxiosCall}>Make axios call</button>

        {show_modal && <SimpleModal handleClose={this.handleModalClose} />}
      </div>
    );
  }
}

I used https://httpstat.us/200 for the test axios call because it always returns 200.