I have a Navbar component in my React app which shows a Sidebar component when screen is small. I used Material UI for the Drawer for displaying the sidebar.
My issue is, on clicking the hamburger icon, drawer opens fine. But it doesn't close when clicking the links or even outside the Sidebar.
How to solve this? What am I doing wrong? Here is my code.
Navbar.js
import React, { useContext, useEffect, useState } from "react";
import "./navbar.css";
import Sidebar from "./Sidebar";
import { NavLink } from "react-router-dom";
import { Drawer } from "#mui/material";
import IconButton from "#mui/material/IconButton";
import MenuIcon from "#mui/icons-material/Menu";
const Navbar = () => {
const [drwOpen, setDrwOpen] = useState(false);
const handleOpen = () => {
setDrwOpen(true);
};
const handleClose = () => {
setDrwOpen(false);
};
return (
<header>
<nav>
<div className="left">
<div className="hamburger" onClick={handleOpen}>
<IconButton>
<MenuIcon style={{ color: "#fff" }} fontSize="large" />
</IconButton>
<Drawer open={drwOpen} onClose={handleClose}>
<Sidebar logClose={handleClose}/>
</Drawer>
</div>
<NavLink to="/">
<img
className="navlogo"
src={process.env.PUBLIC_URL + "/math.png"}
alt="logo"
/>
</NavLink>
</div>
</nav>
</div>
</header>
);
};
export default Navbar;
Sidebar.js
import React from "react";
import { NavLink } from "react-router-dom";
import { useContext, useState } from "react";
import ChevronRightIcon from "#mui/icons-material/ChevronRight";
import "./sidebar.css";
const Sidebar = ({logClose}) => {
return (
<>
<div className="sidebar">
<p>random text</p>
<div className="menu" onClick={()=>logClose()}>
<NavLink to="/" style={{ textDecoration: "none" }} className="lis" >
<p>ABC</p>
<ChevronRightIcon style={{ fill: "#949494" }}/>
</NavLink>
<NavLink to="/" style={{ textDecoration: "none" }} className="lis">
<pXYZ</p>
<ChevronRightIcon style={{ fill: "#949494" }}/>
</NavLink>
<NavLink to="/" style={{ textDecoration: "none" }} className="lis">
<p>123</p>
<ChevronRightIcon style={{ fill: "#949494" }}/>
</NavLink>
</div>
</div>
</>
);
};
export default Sidebar;
The onClick event in <div className="hamburger"> is probably interfering with the open state of your drawer.
Since the drawer is a child of that div, every click on the drawer will propagate and call the onClick event of its parent element as well.
Try putting <Drawer> outside of <div className="hamburger">
Or use event.stopPropagation() in an onClick in the drawer component to stop that behaviour like so:
<Drawer onClick={(event) => {event.stopPropagation()}}>
Hope this could help!
Related
I have some user components on which I used the navigation component and I am routing two components on it. when I click on the Device.js component button it should remove device.js and it should redirect to the Keyregister.js component which is having navigation component in it .It should change the value according to the props sent to it. But it is not happening.
user.js
import React from "react";
import { Route, Switch } from "react-router";
import "./User.css";
import Navigation from "./Dashboard/Navigation";
import AuthModel from "./Dashboard/AuthModel";
import DeviceDetails from "./Dashboard/DeviceDetails";
function User() {
return (
<>
<Navigation
link1={""}
link2={"Authmodel"}
link3={"Requests"}
link1name={"Key Status"}
link2name={"Key Upload"}
link3name={"KEY DOWNLOAD"}
/>
<Switch>
<Route path="/User/Dashboard/AuthModel" component={AuthModel} />
<Route path="/User/Dashboard/DeviceDetails" component={DeviceDetails} />
</Switch>
</>
);
}
export default User;
Navigation.js
import React from "react";
import "./Navigation.css";
import { Link } from "react-router-dom";
import { useHistory } from "react-router";
import { Image } from "react-bootstrap";
import EvoVert from "../../../Resources/EvoluteVert.png";
function Navigation(props) {
const history = useHistory();
const handleLogout = (e) => {
e.preventDefault();
localStorage.removeItem("accessToken");
localStorage.removeItem("roleType");
history.push("/");
};
return (
<>
<main classMain="main">
<aside className="sidebar ">
<Image className="Evo-logo" src={EvoVert} />
<nav className="nav">
<ul style={{ textDecoration: "none" }}>
<li>
<Link to={`/User/Dashboard/${props.link2}`}>
{props.link2name}
</Link>
</li>
<li>
<Link to={`/User/Dashboard/${props.link1}`}>
{props.link1name}
</Link>
</li>
<li>
<Link to={`/User/Dashboard/${props.link3}`}>
{props.link3name}
</Link>
</li>
</ul>
</nav>
</aside>
</main>
</>
);
}
export default Navigation;
Device.js
import React, { useState, useEffect } from "react";
import { Form } from "react-bootstrap";
import "./Dashboard.css";
import { useHistory } from "react-router";
import KeyRegister from "./KeyRegister";
function DeviceDetails() {
const history = useHistory();
const [visible, setvisible] = useState(true);
const [serialNum, setSerialNum] = useState("");
const [slot, setSlot] = useState("");
const frmsubmit = (e) => {};
return (
<>
<section className="device-Details_Dashboard">
<div className="container">
<div
className="heading"
style={{
color: "#312450",
fontWeight: "400",
fontSize: "35px",
padding: "1rem",
}}
>
DEVICE DETAILS
</div>
<Form onSubmit={frmsubmit}>
<div>
<div className="device-details-box">
<label>Serial Number</label>
<br />
<input
type="text"
value={serialNum}
onChange={(e) => setSerialNum(e.target.value)}
/>
</div>
<div className="device-details-box">
<label>Slot Number</label>
<br />
<input
type="text"
value={slot}
onChange={(e) => setSlot(e.target.value)}
/>
</div>
</div>
<button className="devDetSub" onClick={frmsubmit}>
<span>SUBMIT</span>
</button>
</Form>
</div>
</section>
{visible && <KeyRegister />}
</>
);
}
export default DeviceDetails;
KeyRegister.js
import React, { useState, useEffect } from "react";
import "./Navigation.css";
import { Route, Switch } from "react-router";
import DUPKT from "./DUPKT";
import MasterSession from "./MasterSession";
import AES from "./AES";
import Navigation from "./Navigation";
function KeyRegister() {
return (
<>
<Navigation
link1={"DUPKT"}
link2={"MasterSession"}
link3={"AES"}
link1name={"DUPKT"}
link2name={"MASTER KEY"}
link3name={"AES"}
/>
<main classMain="main">
<Switch>
<Route path="/User/Dashboard/DUPKT" component={DUPKT} exact />
<Route
path="/User/Dashboard/MasterSession"
component={MasterSession}
exact
/>
<Route path="/User/Dashboard/AES" component={AES} exact />
</Switch>
</main>
</>
);
}
export default KeyRegister;
I cannot see anywhere in your naviagation component props you are passing device details.
<Navigation
link1={""}
link2={"Authmodel"}
link3={"Requests"}
link1name={"Key Status"}
link2name={"Key Upload"}
link3name={"KEY DOWNLOAD"} //should have device details in props
/>
Goal : display an iframe with a Youtube video and the user can click play/pause
Problem: I can't click on anything in my main content, but it works just fine if I put it in the Navigation component or the Footer component
What I've tried: I tried many debugging to finally found this was the issue, but now I can't figure out what to do
Here is the code of the Navigation component which works fine :
import React, { useState } from "react";
import Navbar from "react-bootstrap/Navbar";
import Nav from "react-bootstrap/Nav";
import Container from "react-bootstrap/Container";
import { Link } from "react-router-dom";
import {NavLink} from "react-router-dom";
import {
AiOutlineHome,
} from "react-icons/ai";
import {Button} from "react-bootstrap";
function Navigation() {
const [expand, updateExpanded] = useState(false);
const [navColour, updateNavbar] = useState(false);
function scrollHandler() {
if (window.scrollY >= 20) {
updateNavbar(true);
} else {
updateNavbar(false);
}
}
window.addEventListener("scroll", scrollHandler);
return (
<Navbar
expanded={expand}
fixed="top"
expand="md"
className={navColour ? "sticky" : "navbar"}
>
<Container>
<Navbar.Brand href="/" className="d-flex">
<p style={{marginTop: "15px"}}><strong className="main-name"> D</strong>egen <strong className="main-name">B</strong>ounty <strong className="main-name">H</strong>unter</p>
</Navbar.Brand>
<Navbar.Toggle
aria-controls="responsive-navbar-nav"
onClick={() => {
updateExpanded(expand ? false : "expanded");
}}
>
</Navbar.Toggle>
<Navbar.Collapse id="responsive-navbar-nav">
<Nav className="ms-auto" defaultActiveKey="#home">
<Nav.Item>
<Nav.Link as={Link} to="/" onClick={() => updateExpanded(false)}>
<AiOutlineHome style={{ marginBottom: "2px" }} /> Home
</Nav.Link>
</Nav.Item>
</Nav>
</Navbar.Collapse>
</Container>
</Navbar>
);
}
export default Navigation;
Here is the code of the Whitepaper component which doesn't allow me to click on anything :
import React from "react";
import {Container, Row, Col} from "react-bootstrap";
import wp_1 from "../Assets/wp_1.png";
function Whitepaper() {
return (<section>
<Container fluid className="whitepaper-section" id="whitepaper">
<Container className="whitepaper-content">
<div>
<button onClick={() => alert("test")}>Add</button>
<iframe
src="https://www.youtube.com/embed/E7wJTI-1dvQ"
frameBorder="0"
allow="autoplay; encrypted-media"
allowFullScreen
title="video"
/>
{" "}
</div>
<Row>
<Col md={12}>
<img src={wp_1} alt="roadmap pic" className="img-fluid" style={{maxWidth: '50%'}}/>
</Col>
</Row>
</Container>
</Container>
</section>);
}
export default Whitepaper;
So once again, when I pass my cursor over the button or the iframe, the cursor shape doesn't change and I can't click. I can select text, select image and right click everywhere.
In the CSS file I looked for pointer-events: none; but I don't have anything like this
What is happening ?
The problem was in the css file I had :
z-index: -1;
Removed this line and it's working fine now
So I have a series of code where a button in the Header.jsx file that if clicked, it will display the content of the Notification.jsx file. The problem here is, I don't exactly know how can I display the content of Notification.jsx in index.js. I tried using conditional statements and is it possible to hide the h1 element once the button is clicked?
Header.jsx
import React from "react";
import { Button } from "#mui/material";
import { IconButton } from "#mui/material";
import NotificationsIcon from "#mui/icons-material/Notifications";
import SearchIcon from "#mui/icons-material/Search";
import Menu from "#mui/material/Menu";
import MenuItem from "#mui/material/MenuItem";
import FullNotifList from "./FullNotifList"
export default function Header() {
const [anchorEl, setAnchorEl] = React.useState(null);
const open = Boolean(anchorEl);
const handleClick = (event) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
return (
<div>
<Button
id="basic-button"
aria-controls={open ? "basic-menu" : undefined}
aria-haspopup="true"
aria-expanded={open ? "true" : undefined}
onClick={handleClick}
>
<IconButton>
<NotificationsIcon />
</IconButton>
</Button>
<Menu
id="basic-menu"
anchorEl={anchorEl}
open={open}
onClose={handleClose}
MenuListProps={{
"aria-labelledby": "basic-button",
}}
>
{/* Button needs to be clicked in order to display Notification.jsx */}
<Button variant="contained">Notification Center</Button>
<MenuItem onClick={handleClose}>Profile</MenuItem>
<MenuItem onClick={handleClose}>My account</MenuItem>
<MenuItem onClick={handleClose}>Logout</MenuItem>
</Menu>
<IconButton>
<SearchIcon />
</IconButton>
</div>
);
}
Notification.jsx
import React from "react";
export default function Notification(){
return(
<div>
<ul>
<li> Hello </li>
<li> Hello </li>
<li> Hello </li>
<li> Hello </li>
</ul>
</div>
)
}
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import reportWebVitals from './reportWebVitals';
import Header from './Header'
import './index.css'
import Footer from './Footer';
import Notification from './Notification';
export default function Page(props) {
const [isClicked, setIsClicked] = React.useState(false)
function showHide(e) {
setIsClicked(true)
};
return(
<div className='main'>
<Header onClick={showHide}/>
{isClicked && <Notification />}
<h1> Sample body </h1>
<Footer />
</div>
)
}
ReactDOM.render(
<Page />,
document.getElementById('root')
);
Here is the sandbox link: https://codesandbox.io/s/friendly-darkness-9u5s22?file=/src/index.js
You just need to create a state property to handle if the element is visible or not (ex: showNotification ) defaulting to false:
const [showNotification, setShowNotification] = React.useState(false);
Then using the button click event to set it to true
<Button variant="contained" onClick={()=>{setShowNotification(true)}}>Notification Center</Button>
Then you implement conditional rendering by using the && operator inside JSX for the return, something like :
{showNotification && <Notification />}
The problem is that your Header component doesn't have prop onClick, so nothing is executing.
What im trying to do is a link between different components in my page, i have a component header with a bunch of links and i want to make reference to anotother component on the same page, in other words im trying to do the following thing but with react:
Hi!
<div id="#move">You have been moved</div>
This is what i have in the header component im using react-bootstrap, i've found some ways to do it without it but i need to do it with it
export default function Header() {
return (
<>
<Navbar variant="dark" expand="lg" style={{ "background-color": "#1A2A4E" }} sticky="top" >
<Navbar.Brand href="#home">Logo</Navbar.Brand>
<Navbar.Toggle aria-controls="basic-navbar-nav" />
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="mr-auto" />
<Nav>
<LinkContainer to={{
hash:"Footer"
}}>
<Nav.Link href="#">Actividades</Nav.Link>
</LinkContainer>
<Nav.Link href="#">Fechas</Nav.Link>
<Nav.Link href="#">Cursos</Nav.Link>
<Nav.Link href="#">Instalaciones</Nav.Link>
<Nav.Link href="#">Contacto</Nav.Link>
</Nav>
</Navbar.Collapse>
</Navbar>
</>
)
}
and then in the App the first link gets the Actividades but the href doesnt work the App component is:
function App() {
return (
<div className="App">
<div className="imagen-fondo" />
<div className="fondo-blaquesino" />
<div className="">
<Header Footer={<Footer/>} />
<Infoinicio />
</div>
<div className="">
<Actividades />
<Cursos />
<InscrCalendario />
<Instalaciones />
<Contacto />
<div id="#Footer" />
<Footer />
</div>
</div>
);
}
So, you want to auto scroll to the selected id, rite? I achieve it using <NavLink /> from reactstrap. Here is how it works
NavigationBar.tsx
import React, { useState } from 'react';
import { withRouter } from 'react-router-dom';
import {
Navbar, NavbarToggler, Collapse,
Nav, NavItem, NavLink,
} from 'reactstrap';
import { HistoryProps } from '../../interfaces';
import './TopBar.scss';
function NavigationBar(props: HistoryProps) {
const [isOpen, setIsOpen] = useState(false);
const toggleNav = () => setIsOpen(!isOpen);
const path = props.history.location.hash;
return (
<Navbar expand="md" className="navbar-wrapper">
<NavbarToggler
onClick={toggleNav}
data-testid="navbar-toggler"
className="navbar navbar-light outline-none"
/>
<Collapse isOpen={isOpen} navbar data-testid="navbar-collapse" className="h-100">
<Nav className="ml-auto h-100" navbar>
<NavItem className="navbar-navitem pl-2 pr-2" active={!path || path.includes('#about-me')}>
<NavLink className="font-size-12" href="#about-me">
About Me
</NavLink>
</NavItem>
</Nav>
</Collapse>
</Navbar>
);
}
export default withRouter(NavigationBar);
And defined the target component/element, in my case, in another component.
LandingPage.tsx
import React from 'react';
import { Row } from 'reactstrap';
import './LandingPage.scss';
export default function LandingPage() {
return (
<div className="container-fluid">
<Row className="about-me-wrapper id-wrapper" id="about-me">
{/* Element here */}
</Row>
</div>
);
}
I am using React.js but I don't achieve to switch modal. Here is my code :
import React from "react";
import ReactDOM from "react-dom";
import moment from "moment";
import { Modal, version, Button } from "antd";
import "antd/dist/antd.css";
import { BrowserRouter, Link, Redirect, Route, Switch } from "react-router-dom";
import Clickthere from "Clickthere";
class App extends React.Component {
state = { visible: false };
showModal = () => {
this.setState({
visible: true
});
};
handleOk = (e) => {
console.log(e);
this.setState({
visible: false
});
};
handleCancel = (e) => {
console.log(e);
this.setState({
visible: false
});
};
render() {
return (
(
<div>
<Button type="primary" onClick={this.showModal}>
Open
</Button>
<Modal
title="Basic Modal"
visible={this.state.visible}
onOk={this.handleOk}
onCancel={this.handleCancel}
>
<p>Some contents...</p>
<p>Some contents...</p>
<p>Some contents...</p>
<p style={{ textAlign: "center" }}>
Other thing?{" "}
<BrowserRouter>
<Link to="/clickthere">
<i className="fas fa-user-plus" /> Click there
</Link>
</BrowserRouter>
</p>
</Modal>
</div>
),
(
<BrowserRouter>
<Switch>
<Route path="/clickthere" component={Clickthere} />
</Switch>
</BrowserRouter>
)
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));
I achieve to open the first modal but I don't achieve when I click on "Click there" nothing happen...
Here is the code of the component Clickthere :
import { Modal } from "react-bootstrap";
import React from "react";
import { BrowserRouter, Switch } from "react-router-dom";
const Clickthere = (props) => {
console.log(props);
return (
<>
<Modal>
<div>
<p>This is a test.</p>
</div>
</Modal>
<BrowserRouter>
<Switch></Switch>
</BrowserRouter>
</>
);
};
export default Clickthere;
Do you know why it does not work ?
Thank you very much !
Here is my code : My code