I am trying to make hamburger menu. I need the styled components to take the info from the state to toggle the menu and it's not happening.
I want that when I click on the open image the sidebar appears and when I click on the close image it disappear.
My Navigation components
import Nav from '../Nav'
import Sidebar from '../Sidebar'
import React, { useState } from 'react'
export const Navigation = () => {
const [isOpen, setIsOpen] = useState(false);
function toggle(){
setIsOpen(!isOpen)
console.log(isOpen)
}
return (
<>
<Sidebar isOpen={isOpen} toggle={toggle}/>
<Nav isOpen={isOpen} toggle={toggle} />
</>
)
}
export default Navigation
The sidebar
import React from 'react'
import { SideContainer, SideList, SideItem,SideTop,SideLogo,SideClose,SideWrapper } from './SidebarElements'
import Logo from '../../assets/shared/desktop/logo.svg'
import close from '../../assets/shared/mobile/icon-close.svg'
const Sidebar = ({isOpen, toggle}) => {
return (
<SideWrapper>
<SideContainer>
<SideTop>
<SideLogo src={Logo} alt="logo" />
<SideClose src={close} isOpen={isOpen} onClick={toggle} alt="close-logo"/>
</SideTop>
<SideList>
<SideItem>HOME </SideItem>
<SideItem>ABOUT US </SideItem>
<SideItem>CREATE YOUR PLAN </SideItem>
</SideList>
</SideContainer>
</SideWrapper>
)
}
export default Sidebar
import styled from 'styled-components';
export const SideWrapper = styled.div`
#media screen and (min-width: 768px) {
display: none;
}
background: white;
position: absolute;
z-index: 999;
top: 0;
justify-content: center;
align-items: center;
text-align: center;
width: 100%;
height: 100%;
transition: 0.3s ease-in-out;
display: flex;
margin-right: ${({ isOpen }) => (isOpen ? "0rem" : "300rem")};
}
The nav
import React from 'react'
import logo from '../../assets/shared/desktop/logo.svg'
import opened from '../../assets/shared/mobile/icon-hamburger.svg'
import { NavLink } from "react-router-dom"
import './nav.css'
import { Nav,NavContainer,NavMenu ,NavLogo,NavOpen } from './NavElements'
const Navbar = ({toggle}) => {
console.log(toggle)
return (
<>
<Nav>
<NavContainer>
<NavLogo src={logo} alt="logo-coffertoast"/>
<NavOpen src={opened} onClick={toggle} alt="logo-open"/>
<NavMenu>
<NavLink className="Items" to="/">HOME</NavLink>
<NavLink className="Items" to="/about">ABOUT US</NavLink>
<NavLink className="Items" to="/plan" >CREATE YOUR PLAN</NavLink>
</NavMenu>
</NavContainer>
</Nav>
</>
)
}
export default Navbar
You are not passing isOpen to SideWrapper -
<SideWrapper>
it should be
<SideWrapper isOpen={isOpen}>
Related
I don't know why when i click on the About icon (or other icons in the menu bar), I get the text under my NavBar instead of having it next to it.
The NavBar.jsx component:
import './NavBar.css'
import logo from "../Components/logo";
import { ITEMS } from "../Navigation";
import React from 'react'
export default function NavBar() {
return (
<div className="NavBar">
<img className="logo" />
<span className="textLogo">LOGO</span>
<div className ="NavbarList">
{ITEMS.map((item, i) => {
return (
<li key={i} className="row" id={window.location.pathname === item.href ? "active" : ""}
onClick={() => {window.location.pathname = item.href;}}>
<div id="icon">{item.icon}</div>
<div id="title">{item.title}</div>
</li>
);
})}
</div>
</div>
);
}
My NavBar.css :
.NavBar{
width: 15rem;
height: 100vh;
padding-top: 1rem;
padding-bottom: 1rem;
--tw-bg-opacity: 1;
background-color: rgb(35,37,79);
flex-direction: column;
gap: 1.25rem
}
.NavbarList{
padding-top:20px;
}
...
And here the picture of what i get (there are other icons above About):
(I'm not able to put all the css file, because it says "too many codes")
i want to split page between styling and app
example
in page style.js
import styled from "styled-components";
//i dont know how to export all const
export const Container = styled.div`
display: flex;
flex-direction: row;
`;
export const Sidebar = styled.div`
width: 20%;
height: 100%;
background-color: #f9f9f9;
`;
and in page app.js
import * as All from "./style.js"
//i dont know, how to import all const in style.js
function App(){
return(
<Container>
<Sidebar>
</Sidebar>
</Container>
)}
how to export and import all const when const in style.js there are so many?
another option you can export like this :
import styled from "styled-components";
const Container = styled.div`
display: flex;
flex-direction: row;
`;
const Sidebar = styled.div`
width: 20%;
height: 100%;
background-color: #f9f9f9;
`;
export {Container,Sidebar}
and you can import like this :
import { Container,Sidebar } from './style';
function App() {
return (
<Container>
<Sidebar>
</Sidebar>
</Container>
);
}
There is a beautiful way to do that. This way also let you know which component is styled-component or single component.
// style.js
export const Styled = {
Container: styled.div`
display: flex;
flex-direction: row;
`,
Sidebar: styled.div`
width: 20%;
height: 100%;
background-color: #f9f9f9;
`,
}
import { Styled } from './style';
function App() {
return (
<Styled.Container>
<Styled.Sidebar>
</Styled.Sidebar>
</Styled.Container>
);
}
Dae Hyeon Mun's approach is great, but you can simplify it further and avoid having to refactor your styles.js file by using a wildcard import, which essentially creates a module object so you don't have to!:
// style.js
export const Container = styled.div`
...
`;
export const Sidebar = styled.div`
...
`;
// app.js
import * as Styled from './style';
function App() {
return (
<Styled.Container>
<Styled.Sidebar>
</Styled.Sidebar>
</Styled.Container>
);
}
More details: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules#creating_a_module_object
You can use "export const" like you already did for exporting. The simplest way to import those const is:
import * as styled from "./style.js"
//this will import all 'export const' containing 'styled' from "./style.js"
function App(){
return(
<Container>
<Sidebar>
</Sidebar>
</Container>
)}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
I am having a unique scenario but I am unable to understand this.
When I hover on one DIV then it selects both the sibling DIVS.
I do not want this behaviour.
I want to select only the DIV which is being hovered.
How can I achieve this in ReactJS ?.
The working code is shown below.
App.js
import React,{useState} from 'react';
import "./App.css";
const App = () => {
const [hover, setHover] = useState(false);
const texts = ["Arjun", "Andy"];
let cclass = hover ? "item itemHover":"item";
return (
<div className="wrapper">
{
texts.map((t, i) => (
<div className={cclass} key={i} onMouseEnter={() => setHover(true)}
onMouseLeave={() => setHover(false)}>
{t}
</div>
))
}
</div>
)
}
export default App;
App.css
.wrapper{
width: 60%;
margin: 10rem auto;
border: 1px solid;
display: flex;
}
.item{
width: 50%;
border: 1px solid grey;
height: auto;
padding: 2rem 3rem;
}
.itemHover{
background: grey;
}
The hover state in App is common for both divs. To make it work you need to
have hover state for each div separate. For this, create a new component TextDiv
import React, {useState} from "react";
import "./styles.css";
export default function TextDiv({t}) {
const [hover, setHover] = useState(false);
let cclass = hover ? "item itemHover":"item";
return (
<div className={cclass} onMouseEnter={() => setHover(true)}
onMouseLeave={() => setHover(false)}>
{t}
</div>
)
}
and change App.js file
import React, {useState} from "react";
import TextDiv from './TextDiv'
import "./styles.css";
export default function App() {
const texts = ["Arjun", "Andy"];
return (
<div className="wrapper">
{
texts.map((t, i) => (
<TextDiv t={t} key={i}/>
))
}
</div>
)
}
Can you do it with CSS? It's very simple with CSS. Just add this:
.item:hover{
background: grey;
}
I changed the anchor tag to the Link tag and the whole component doesn't display. It is note worthy that I had used the anchor tag and it was properly rendered. However, after changing to the Link tag nothing gets displayed again. Below is what my code looks like:
Navbar component
import React, {Component} from 'react';
import { Link } from 'react-router';
class Navbar extends Component {
render() {
return (
<div className="Navbar">
<ul className="navbar-list">
<li className="active"><Link to={"/home"}>Home</Link></li>
<li><Link to={"/about"}>About Us</Link></li>
<li><Link to={"/pricing"}>Pricing</Link></li>
</ul>
</div>
)
}
}
export default Navbar
css
.navbar-list {
list-style-type: none;
padding: 0;
margin: 0;
overflow: hidden;
background-color: #333;
}
.navbar-list li{
float: left;
}
.navbar-list li Link {
display: block;
color: white;
text-align: center;
padding: 14px 16px;
text-decoration: none;
}
.navbar-list li Link:hover{
background-color: #111 ;
}
.active {
background-color: #4CAF50;
}
App.js file
class App extends Component {
render() {
return (
<div className="App">
<Navbar />
</div>
);
}
}
export default App;
There is some issue in Link from react-router
Instead try using
import { NavLink } from 'react-router-dom';
You code will look like this:
in dependencies of your package.json and do npm i: include:
"react-router-dom": "5.0.0",
import { BrowserRouter as Router } from "react-router-dom";
class App extends Component {
render() {
return (
<div className="App">
<Router>
<Navbar />
<Router>
</div>
);
}
}
export default App;
import React, { Component } from 'react';
import { NavLink } from 'react-router-dom';
class Navbar extends Component {
render() {
return (
<div className="Navbar">
<ul className="navbar-list">
<li className="active"><NavLink to={"/home"}>Home</NavLink></li>
<li><NavLink to={"/about"}>About Us</NavLink></li>
<li><NavLink to={"/pricing"}>Pricing</NavLink></li>
</ul>
</div>
)
}
}
export default Navbar;
Maybe you can try to change To prop on string like this :
<Link to="/pricing">Pricing</Link>
Another thing u can try is install react-router-dom instead of react-router.
Hi guys very simple question. I have a home page and a room page. The question is why is the logo image in the navbar component loading in the homepage but not in the room page?
The home page is as follows:
import React from 'react';
import Hero from '../components/hero.js';
import NavBar from '../components/navbar.js';
import Services from '../components/services.js';
import FeaturedRooms from '../components/featuredRooms.js';
import Consultation from '../components/consultation.js';
import Footer from '../components/footer.js';
const Home = () => {
return (
<React.Fragment>
<NavBar/>
<Hero/>
<Services/>
<FeaturedRooms/>
<Consultation/>
<Footer/>
</React.Fragment>
);
}
export default Home;
The room page is basic right now and is only:
import React from 'react';
import NavBar from '../components/navbar';
import Footer from '../components/footer';
const RoomPage = () => {
return (
<React.Fragment>
<NavBar/>
<Footer/>
</React.Fragment>
);
}
export default RoomPage;
The route for the logo image is public/images/logo.png. I import the logo with src="images/logo.png" for an img as a styled component in my navbar component.
Both the homepage and the room page are in the same folder: src/pages/home.js and src/pages/singleRoom.js
The navbar is in the components folder as follows: src/components/navbar.js
Here is the navbar.js code:
import React from 'react';
import styled from 'styled-components';
import {Link} from 'react-router-dom';
import {LinkWithNoStyling} from './shared';
const Header = styled.header`
display: flex;
justify-content: flex-end;
padding: 10px 10%;
box-sizing: border-box;
background-color: rgb(251, 251, 251);
`;
const Logo = styled.img`
height: 30px;
/* explanation: margins top and bottom for flex child center vertically, given a margin right of auto and left of 0 we make it stick to the left. */
margin: auto auto auto 0;
`;
const UnorderedList = styled.ul`
list-style: none;
display: flex;
`;
const ListItem = styled.li`
margin-left: 35px;
`;
const MenuAnchor = styled.a`
text-decoration: none;
font-size: 1rem;
font-weight: bold;
color: black;
&:hover {
color: rgb(161, 113, 1);
}
`;
const Navbar = () => {
return (
<Header>
<Logo src="images/logo.png"/>
<nav>
<UnorderedList>
<ListItem>
<LinkWithNoStyling to="/">
<MenuAnchor href="">Home</MenuAnchor>
</LinkWithNoStyling>
</ListItem>
<ListItem>
<LinkWithNoStyling to="/rooms">
<MenuAnchor href="">Rooms</MenuAnchor>
</LinkWithNoStyling>
</ListItem>
</UnorderedList>
</nav>
</Header>
);
}
export default Navbar;
Finally, here is the App.js code:
import React from 'react';
import './App.css';
import {BrowserRouter, Switch, Route} from 'react-router-dom';
import Home from './pages/home';
import NotFound from './pages/notFound';
import Rooms from './pages/rooms';
import RoomPage from './pages/roomPage'
function App() {
return (
<div className="App">
<BrowserRouter>
<Switch>
<Route path="/" component={Home} exact/>
<Route path="/rooms" component={Rooms} exact/>
<Route path="/room/:id" component={RoomPage} exact/>
<Route path="/" component={NotFound}/>
</Switch>
</BrowserRouter>
</div>
);
}
export default App;
You're using a relative url for the src attribute on the Logo component. images/logo.png points relative to the current path, so for your home page, it points to <url>/images/logo.png, but for your room page, it points to <url>/room/:id/images/logo.png. If you change your src to /images/logo.png, then it will always point to the proper file. For more info about html file paths, check here.