0

I'm new to react thus the question. This is my CustomModal,

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

const CustomModal = (props) =>{
    const [show, setShow] = useState(true);
    const handleClose = () => setShow(false);

    return (
        <div>
            <Modal show={show} animation={false}>
                <Modal.Header closeButton>
                    <Modal.Title>Modal heading</Modal.Title>
                </Modal.Header>
                <Modal.Body>{props.message}</Modal.Body>
                <Modal.Footer>
                    <Button variant="secondary" onClick={handleClose}>
                        Close
                    </Button>
                </Modal.Footer>
            </Modal>
        </div>
    )
};
export default CustomModal;

I want to render it inside a class component when user submits a registration form.

class Register extends React.Component {
    state = {
        email : '',
        username: '',
        password: '',
        second_password: ''
    };
    handleSubmit = async (event) =>{
        event.preventDefault();

        const emailValidated = await this.validateEmail(this.state.email);
        const usernameValidated = this.validateUsername(this.state.username);
        const passwordValidated = this.validatePassword(this.state.password, this.state.second_password);
        let registrationComplete = false;
        if(emailValidated === true && usernameValidated === true && passwordValidated === true){
            registrationComplete = await this.register(this.state.email, this.state.username, this.state.password);
            console.log(registrationComplete);
            this.showModal("Hello World!"); //This is the function begin called to show the modal.
        }

    };
    validateUsername = (username) =>{
        return true;
    };

    validatePassword = (password, second) =>{
        return true;
    };

    validateEmail = async (email) =>{
        return true;
    };


    //This is the function that should display the modal

    showModal = (message) =>{
        return (<CustomModal message={message}/>);
    };


    register = async (email, username, password) =>{
        return true;
    };
    render() {
        return (
            <div className="register">
                <h1>Register</h1>
                <Form onSubmit={this.handleSubmit}>
                    <Form.Group controlId="formBasicEmail">
                        <Form.Label>Email address</Form.Label>
                        <Form.Control type="email"
                                      placeholder="Enter email"
                                      value={this.state.email}
                                      onChange={event => this.setState({email: event.target.value})}/>
                        <Form.Text className="text-muted">
                            Please make sure you've access to this mail. You'll receive an activation code here.
                        </Form.Text>
                    </Form.Group>

                    <Form.Group controlId="formPlainText">
                        <Form.Label className="form-label">Username</Form.Label>
                        <Form.Control type="text"
                                      placeholder="Username"
                                      value={this.state.username}
                                      onChange={event => this.setState({username: event.target.value})}/>
                        <Form.Text className="text-muted">
                            Please make it atleast 8 characters long.
                        </Form.Text>
                    </Form.Group>

                    <Form.Group controlId="formBasicPassword">
                        <Form.Label>Password</Form.Label>
                        <Form.Control type="password"
                                      placeholder="Password"
                                      value={this.state.password}
                                      onChange={event => this.setState({password: event.target.value})}/>
                        <Form.Text className="text-muted">
                            Please make sure it's atleast 8 characters long and uses a mix of letters and numbers.
                        </Form.Text>
                    </Form.Group>

                    <Form.Group controlId="formBasicPassword">
                        <Form.Label>Retype Password</Form.Label>
                        <Form.Control type="password"
                                      placeholder="Password"
                                      value={this.state.second_password}
                                      onChange={event => this.setState({second_password: event.target.value})}/>
                    </Form.Group>


                    <Button variant="primary" type="submit">
                        Register
                    </Button>
                </Form>
            </div>
        );
    }
}
export default Register;

All the values are correct and the console log shows true but the Modal doesn't display. Can someone help me with this?

Melissa Stewart
  • 3,483
  • 11
  • 49
  • 88
  • You need to a) add `modalOpen: false` to your main component's `state`, b) add `{this.state.modalOpen && }` to your JSX c) instead of returning something from `showModal` that is instantly discarded, call `this.setState({ showModal: true });` (to close the modal again, you need to pass and call a `closeModal` prop that contains a function that sets `Register`'s state back to `modalOpen: false`) –  Dec 28 '19 at 02:35
  • @ChrisG I'm really new to react, if you could write a more detailed answer it would really help. – Melissa Stewart Dec 28 '19 at 02:41
  • 1
    Here's a minimal example: https://codesandbox.io/s/nervous-galileo-6x2fd –  Dec 28 '19 at 03:17

2 Answers2

1

There are some issues on your code

  1. The customModal has to be part of the render of the Register component
  2. There should be a state to track the status of the modal from the Register component
  3. Also the register has to be notified when the Modal closes

I have modified your code and working. You can find it live here

Dan Hunex
  • 5,172
  • 2
  • 27
  • 38
  • This is great and mostly working. But I'm new to react thus could you do a minor refactor and wrap the rendering of the modal into the showmodal function so that I can call it with a custom message everytime. I want to show the modal even with failure messages. – Melissa Stewart Dec 28 '19 at 15:40
  • Nnm figure it out. Thanks a lot. – Melissa Stewart Dec 28 '19 at 15:50
0

I prefer attack this problem creating portals here documentation.

you might to have issues with z-index in the future.

Basically, you create an element outside the DOM hierarchy.

Now, your issue is that, you must render modal inside render method and control it, with boolean state "showModal".

I prepare for you an example:

example in my GitHub account

  • git clone ...
  • npm install
  • npm run start

preview:

enter image description here

ene_salinas
  • 705
  • 4
  • 11
  • 1
    OP is using `react-boostrap`; I don't think you need portals to use its modals. Also, your answer is supposed to contain code; a link to a github repo is not enough since it can in theory break down at any point, rendering the answer useless. –  Dec 28 '19 at 09:39