The sidebar is automatically rendered even i have functionality to implement with click on pizza icon
Main.js component , in this component the functionality of useState Hook for toggling the sidebar is implemented
import React, { useState } from 'react';
import { Navbar } from '../NavBar/Navbar';
import { SideBar } from '../SideBar/sidebar';
import { MainContainer,MainContent,MainItem,MainH1,MainP1,MainButton } from './MainElements';
export const Main = () => {
const [isOpen, setIsOpen] = useState(false);
const toggle = () => {
setIsOpen(!isOpen);
};
return (
<MainContainer>
<Navbar toggle={toggle}/>
<SideBar isOpen={isOpen} toggle={toggle} />
<MainContent>
<MainItem>
<MainH1>
Greatest Pizza Ever
</MainH1>
<MainP1>
Ready as early in the 5 Minutes
</MainP1>
<MainButton>Submit</MainButton>
</MainItem>
</MainContent>
</MainContainer>
)
}
Sidebar.js component which is automatically rendered on the screen
import { SidebarContainer,Icon,CloseIcon,SidebarMenu,SidebarLink,SidebarBtn,SidebarRoute } from "./sidebar.element";
export const SideBar = ({isOpen,toggle})=> {
return(
<SidebarContainer isOpen={isOpen} onClick={toggle}>
<Icon onClick={toggle}>
<CloseIcon/>
</Icon>
<SidebarMenu>
<SidebarLink to="/">Pizzas</SidebarLink>
<SidebarLink to="/">Desserts</SidebarLink>
<SidebarLink to="/"> Full Menu</SidebarLink>
</SidebarMenu>
<SidebarBtn>
<SidebarRoute to="/">Order Now</SidebarRoute>
</SidebarBtn>
</SidebarContainer>
);
}
Navbar.js component which holds the icon and props toggle
import React from 'react';
import { Nav, NavLink, NavIcon, PizzaIcon} from './NavbarElements';
export const Navbar = ({toggle}) => {
return (
<Nav>
<NavLink to='/'>
Muncheese
</NavLink>
<NavIcon onClick={toggle}>
<p>Menu</p>
<PizzaIcon/>
</NavIcon>
</Nav>
)
}
Not so sure what your isOpen do. Did you declare that part inside SidebarContainer?
Try changing it to render conditionally like this
{ isOpen ? <SideBar toggle={toggle}/> : null }
Also its worth pointing out that within your sidebar, you've already set an onClick event listener for the whole sidebar component. The onClick within your Icon is not necessary unless you want a specific part of this component to perform the toggle function then you need to remove the onClick in SidebarContainer.
<SidebarContainer isOpen={isOpen} onClick={toggle}>
Related
Small premise: I'm not a great Typescript expert
Hi everyone, I'm working on my personal site, I decided to develop it in Typescript to learn the language.
My component tree is composed, as usual, of App.tsx which render the sub-components, in this case Navbar.jsx and Home.jsx.
Below is the App.jsx code:
import './App.css';
import { BrowserRouter as Router, useRoutes } from 'react-router-dom';
import Home from './components/Home';
import Navbar from './components/Navbar';
import { useState } from 'react';
function App(){
const [navbarScroll,setNavbarScrool]=useState(Object)
const handleLocationChange = (navbarScroll : boolean) => {
setNavbarScrool(navbarScroll)
return navbarScroll
}
const AppRoutes = () => {
let routes = useRoutes([
{ path: "/", element: <Home handleLocationChange={handleLocationChange}/> },
{ path: "component2", element: <></> },
]);
return routes;
};
return (
<Router>
<Navbar navbarScroll={navbarScroll}/>
<AppRoutes/>
</Router>
);
}
export default App;
Here, instead, the Home.jsx code:
import { useInView } from 'react-intersection-observer';
import HomeCSS from "../styles/home.module.css"
import mePhoto from "../assets/me.png"
import { useEffect, useState } from 'react';
interface AppProps {
handleLocationChange: (values: any) => boolean;
}
export default function Home(props: AppProps){
const { ref: containerChange , inView: containerChangeIsVisible, entry} = useInView();
useEffect(()=>{
props.handleLocationChange(containerChangeIsVisible)
//returns false at first render as expected
console.log("Home "+containerChangeIsVisible)
},[])
return(
<>
<div className={`${ HomeCSS.container} ${containerChangeIsVisible? HomeCSS.container_variation: ''}`}>
<div className={HomeCSS.container__children}>
{/* when i scroll on the div the css change (this works)*/}
<h1 className={`${ HomeCSS.container__h1} ${containerChangeIsVisible? HomeCSS.container__h1_variation: ''}`}>My<br/> Name</h1>
<p>Computer Science student.</p>
</div>
<img src={mePhoto} className={HomeCSS.image_style}/>
</div>
<div ref={containerChange} style={{height:800,background:"orange"}}>
<p style={{marginTop:20}}>HIII</p>
</div>
</>
)
}
And Navbar.jsx:
import NavbarCSS from "../styles/navbar.module.css"
import acPhoto from "../assets/ac.png"
import { Link } from "react-router-dom";
import { useEffect, useState } from "react";
interface NavbarScroolProp{
navbarScroll:boolean
}
export default function Navbar(props:NavbarScroolProp){
const [scrollState,setScrollState]=useState(false)
const [pVisible,setpVisible] = useState('')
useEffect(()=>{
setTimeout(() => {
setpVisible("")
}, 3000)
setpVisible("100%")
},[])
//returns false also when should be true
console.log(props.navbarScroll)
return (
<>
{/*the props is undefined so the css doesn't change, i need to do this*/}
<nav className={`${props.navbarScroll?NavbarCSS.nav__variation:NavbarCSS.nav}`}>
<div className={NavbarCSS.nav_row}>
<div className={NavbarCSS.nav_row_container}>
<img src={acPhoto} className={NavbarCSS.image_style}/>
<p className={NavbarCSS.p_style} style={{maxWidth: pVisible}}>My name</p>
</div>
<div className={NavbarCSS.nav_row_tagcontainer}>
<Link className={NavbarCSS.nav_row_tag} to="/"> Home</Link>
<Link className={NavbarCSS.nav_row_tag} to="/"> About</Link>
<Link className={NavbarCSS.nav_row_tag} to="/"> Contact</Link>
</div>
</div>
</nav>
</>
);
}
In my application I want to change the background color whenever the div referring to the InsertionObserver ( I use "useInView" hook , from :https://github.com/thebuilder/react-intersection-observer) is displayed. The problem is that the div in question is in the Home.jsx component and I need to change the color of the divs in the navbar as well when the div in Home is triggered(or other components in case I need to in the future).
The question is: How can I dynamically trigger DOM elements of other components (to then perform certain operations) using the InsertionObserver ?
As you can see from the code I tried to create Props, but everything returns undefined and doesn't involve any changes.
I've tried without useEffect, without using the useInView hook, passing the object instead of the boolean value, but I can't find any solutions to this problem.
You would be of great help to me.
PS: I would like to leave the Navbar.jsx component where it is now, so that it is visible in all components.
Any advice or constructive criticism is welcome.
I want to change the width of a component whenever I click a button from another component
This is the button in BiCarret:
import { useState } from "react";
import { BiCaretLeft } from "react-icons/bi";
const SideBar = () => {
const [open, setOpen] = useState(true);
return (
<div className="relative">
<BiCaretLeft
className={`${
open ? "w-72" : "w-20"
} bg-red-400 absolute cursor-pointer -right-3 top-5 border rounded-full`}
color="#fff"
size={25}
onClick={setOpen(!true)}
/>
</div>
);
};
export default SideBar;
and this is the component I want to change the width on click
import "./App.css";
import SideBar from "./components/SideBar/SideBar";
function App() {
return (
<div className="app flex">
<aside className="h-screen bg-slate-700"> // change the width here
<SideBar />
</aside>
<main className="flex-1 h-screen"></main>
</div>
);
}
export default App;
You have two simple solutions, either:
Create context
Crete context and store Open value in it, change it on click and in App react to it.
Dom manipulation
In app add ID to element you would like to change and onClick in the other component use document.getElementById(THE_ID).classList.add("new-class-for-increased-width") which gets the DOM element and adds class to it.
I've got a problem about mui Drawers. As I see on the internet, drawer never removes the content of the page, but in my case yes it does :( Can you help me to figure out what is the problem?
here is my Drawer component code:
import Drawer from '#mui/material/Drawer';
import { useState } from 'react';
import Box from "#mui/material/Box";
export default function SideBar() {
const [isDrawerOpen, setDrawerOpen] = useState(false);
return (
<div>
<button onClick={() => setDrawerOpen(true)}>left</button>
<Drawer
anchor="right"
open={isDrawerOpen}
onClose={() => setDrawerOpen(false)}
>
<Box>sdfsd</Box>
</Drawer>
</div>
)
;
}
And I call it on this page.
import Drawer from "../components/SideBar"
export default function ShopSingle(){
<div>
{/* <Navbar></Navbar>
<HeaderHome></HeaderHome> */}
<div>
PAGE CONTENT
<Drawer></Drawer>
</div>
{/* <Footer></Footer> */}
</div>
}
I'm pretty new with React, can you help me the solve problem?
I want to toggle class of container (file 2) by an onClick on the button that is inside another component file.
The button has already an onClick function and I want to make it so it calls on two functions. Two toggle functions for the button and two class toggles for the container.
Hope it makes sense.
Here is my code so far:
Button component (File 1)
import React, {useState} from "react";
import "./Sort.scss";
const Sort = () => {
const [toggleSortIcon, toggleSortIconSet] = useState(false);
return (
<div className="tools">
<button
onClick={() => toggleSortIconSet(!toggleSortIcon)}
className={`sort ${toggleSortIcon ? "horizontal" : "vertical"}`}>
</button>
</div>
);
}
export default Sort;
Div container component that I want to change the class of (File 2)
import React, {useState} from "react";
import "./WordContainer.scss";
import UseAnimations from "react-useanimations";
const WordContainer = ({title, definition, example}) => {
const [toggleSize, toggleSizeState] = useState(false);
return (
<div className={`container ${toggleSize ? "big" : "small"}`}>
<div className="content">
<h2>{title}</h2>
<p>{definition}</p>
<h3>Example</h3>
<p>{example}</p>
</div>
<img onClick={() => toggleSizeState(!toggleSize)} src="./resize.svg" alt="resize" className="resize"/>
<div className="bookmark">
<UseAnimations
animationKey="bookmark"
size={26}
/>
</div>
</div>
);
}
export default WordContainer;
You could either have a global state management system (redux, or with custom hooks) that you can use to store the icon size.
Or you could simply provide a callback to your component that stores the icon size in a parent component that then feeds it back to your
Something like this:
const [size, setSize] = useState(/* default value */);
render() {
<>
<Sort onSizeToggle={setSize} />
<WordContainer size={size} />
</>
}
I have read some introductions on React Hooks and want to make a simple app with a button in the header component, which determines if the main app should show the sidebar. The button sets the variable showSidebar in the header, and I want to read it again within my main component. The code for actually showing the sidebar is stripped out for brevity.
This is index.js:
import React, { useState } from "react";
import ReactDOM from "react-dom";
import Header from "./header";
import "./styles.css";
function App() {
const [showSidebar, setShowSidebar] = useState(true);
return (
<div className="App">
<Header />
<h1>Sidebar toggler</h1>
<p>
Should I show sidebar? <b>{showSidebar.toString()}</b>
</p>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
And this is the header.js:
import React, { useState } from "react";
export default function Header() {
const [showSideBar, setShowSidebar] = useState(true);
const toggleSidebar = () => setShowSidebar(!showSideBar);
return (
<header>
Button in header toggles sidebar:
<button onClick={() => toggleSidebar()}>
Toggle sidebar (state: {showSideBar.toString()})
</button>
</header>
);
}
I am new to React, but do not understand why the state does not update in index.js? I also made a CodeSandbox with the code.
useState is stores local state, for comparison you can think of it similar to setState in a class component (although in reality they aren't exactly equivalent). Therefore, setting setShowSidebar in App won't reflect the same value as that set in Header and vice versa.
It doesn't look like Header needs any form of local state if it's simply changing state of the outer component, you can pass in an event handler and any relevant state Header needs as props instead
index.js
function App() {
const [showSidebar, setShowSidebar] = useState(true);
const toggleSidebar = useCallback(() => setShowSidebar(value => !value));
return (
<div className="App">
<Header onClick={toggleSidebar} showSideBar={showSidebar} />
<h1>Sidebar toggler</h1>
<p>
Should I show sidebar? <b>{showSidebar.toString()}</b>
</p>
</div>
);
}
header.js
export default function Header(props) {
return (
<header>
Button in header toggles sidebar:
<button onClick={props.onClick}>
Toggle sidebar (state: {props.showSideBar.toString()})
</button>
</header>
);
}
What you're doing wrong is declaring a separate state in Header which you shouldn't do, because it has nothing to do with parent's state. Pass the parent state and a callback to update the parent state as a props to the header. Pass showSidebar as props to the Header component:
import React, { useState } from "react";
import ReactDOM from "react-dom";
import Header from "./header";
import "./styles.css";
function App() {
const [showSidebar, setShowSidebar] = useState(true);
return (
<div className="App">
// Pass prop here
<Header
showSidebar={showSidebar}
toggleSidebar={()=>{setShowSidebar(!showSidebar)}}
/>
<h1>Sidebar toggler</h1>
<p>
Should I show sidebar? <b>{showSidebar.toString()}</b>
</p>
</div>
);
}
// and then in your Header,
export default function Header(props) {
return (
<header>
Button in header toggles sidebar:
<button onClick={props.toggleSideBar}>
Toggle sidebar (state: {props.showSideBar.toString()})
</button>
</header>
);
}
You want to keep state showSidebar in the parent component (where you need to read it) and pass the functionality to change it to the header component (where you need to change showSidebar)
To do move toggleSidebar to index.js
const toggleSidebar = () => setShowSidebar(!showSideBar);
and pass the function to the Header component like this
<Header toggleSidebar={toggleSidebar} />
now invoke it on clickEvent in Header component like this
<button onClick={() => toggleSidebar()}>
remember to include the prop in your Header component
export default function Header({toggleSidebar}) {
You should have your toggleSidebar function in App.js itself, and pass toggleSidebar function and showSidebar state in Header component as props.
App.js
function App() {
const [showSidebar, setShowSidebar] = useState(true)
const toggleSidebar = () => setShowSidebar(!showSidebar)
return (
<div className="App">
<Header showSideBar={showSidebar} onClick={toggleSidebar} />
<h1>Sidebar toggler</h1>
<p>
Should I show sidebar? <b>{showSidebar.toString()}</b>
</p>
</div>
)
}
Header.js
import React from 'react'
export default function Header(props) {
return (
<header>
Button in header toggles sidebar:
<button onClick={props.onClick}>
Toggle sidebar (state: {props.showSideBar.toString()})
</button>
</header>
)
}
Demo