问题
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