Modal not showing up in react with react-bootstrap

泄露秘密 提交于 2020-06-01 04:44:52

问题


I am trying to create a modal to have a login/register pop-up when clicking on the NavBar.Item Login/Register.

My modal is defined as below:

import React from "react";
import '../assets/styles/GenericTheme.css'
import { Modal } from "react-bootstrap";

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

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

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

    render() {  
        return (         
     //   <Modal show={this.state.show} onHide={this.close} dialogClassName="popup-inner">
        <Modal show={this.state.show} fade={false} style={{width: "200px", display: "block"}}>
            <Modal.Body>test</Modal.Body>
        </Modal>
        );  
    }  
}  

export default LoginRegisterModal;

In the NavBar, I have added the reference to the Modal as below:

import React, {}  from 'react';
import { Navbar, Nav, NavDropdown } from 'react-bootstrap';
import SearchForm from '../HeaderFooter/SearchForm';
import SiteLogo from '../../assets/images/village-logo.svg';
import '../../assets/styles/HeaderTheme.css'
import LoginRegisterModal from '../LoginRegisterModal';


class NavHeader extends React.Component {

    constructor(props, context) {
        super(props);
        this.state = {showLogin: false};
    }

    openLogin = () => {
        this.setState({showLogin: !this.state.showLogin});
    }

    render() {
        return (
            <div>
            <Navbar className="village-header" width="100" expand="lg">
                <Navbar.Brand href="/">
                    <img
                        src= { SiteLogo }
                        width="214"
                        height="28"
                        className="d-inline-block align-top"
                        alt="Village"
                    />
                </Navbar.Brand>
                <SearchForm />
                <Navbar.Toggle aria-controls="basic-navbar-nav" />
                <Navbar.Collapse id="basic-navbar-nav">
                    <Nav className="mr-auto village-header">
                    <Nav.Link href="/discover">Discover</Nav.Link>
                    <Nav.Link href="/create">Create</Nav.Link>
                    <Nav.Link href="/howitworks">How it Works</Nav.Link>
                    <Nav.Link ref="LoginRegisterModal" eventKey={1} href="#" onClick={this.openLogin}>Login/Register</Nav.Link>
                    <NavDropdown title="Profile" id="basic-nav-dropdown">
                        <NavDropdown.Item>Firstname LastName</NavDropdown.Item>
                        <NavDropdown.Divider />
                        <NavDropdown.Item href="/profile">Profile</NavDropdown.Item>
                        <NavDropdown.Item href="/messages">Messages</NavDropdown.Item>
                        <NavDropdown.Item href="/settings">Settings</NavDropdown.Item>
                        <NavDropdown.Item href="/logout">Logout</NavDropdown.Item>
                    </NavDropdown>
                    </Nav>
                </Navbar.Collapse>
            </Navbar>
            <LoginRegisterModal show={this.state.showLogin} />
            </div>
            );
        }
}

export default NavHeader;

When I click on the Login/Register:

<Nav.Link ref="LoginRegisterModal" eventKey={1} href="#" onClick={this.openLogin}>Login/Register</Nav.Link>

nothing happens, no pop-up or modal is shown. Also I have added the line below in the NavBar

<LoginRegisterModal show={this.state.showLogin} /> but nothin change. I tried also by adding a className and forcing the z-layer to 2 but it's not working as well.

Any ideas ? Regards


回答1:


Your modal component isn't "listening" for any passed props, i.e. the show prop being passed from NavHeader. A quick dirty would be to implement the componentDidUpdate lifecycle function to check for the show prop value change. Also use the show prop value to set initial state in the case it's displayed open upon mounting.

class LoginRegisterModal extends React.Component {  
  constructor(props, context) {
    super(props);
    this.state = {
      show: props.show, // use the initial show value
    };
  }

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

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

  componentDidUpdate(prevProps) {
    const { show } = this.props;
    if (prevProps.show !== show && show) {
      open(); // open if parent says to
    } else {
      close(); // close if parent says to
    }
  }

  render() {  
    return (         
    //   <Modal
    //     show={this.state.show}
    //     onHide={this.close}
    //     dialogClassName="popup-inner"
    //   >
      <Modal
        show={this.state.show}
        fade={false}
        style={{width: "200px", display: "block"}}
      >
        <Modal.Body>test</Modal.Body>
      </Modal>
    );  
  }  
}

This allows the parent to to toggle the modal's display state, but what if the modal is closed/dismissed from within. You may want some way to signal back out to the NavHeader that the modal was closed so it can "sync" its state. The onHide prop does that, and you have it commented out. I suggest also exposing out to the LoginRegisterModal API an onHide prop.

close = () => {
  this.setState({show: false});
  this.props.onHide();
}

The the parent uses as such

<LoginRegisterModal
  show={this.state.showLogin}
  onHide={() => this.setState({ showLogin: false })}
/>

This however, creates code duplication. It may be a better design to make LoginRegisterModal a controlled component and simply pass the show and onHide props passed from NavHeader to the internal Modal component of LoginRegisterModal.



来源:https://stackoverflow.com/questions/62112514/modal-not-showing-up-in-react-with-react-bootstrap

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!