I need some help... I'm building a multi-page B&B app using React (Vite) and React Router Dom. I'm also using React Query, React Scroll Parallax, Material UI and Redux Toolkit.
Here's my problem:
If I click on most of the NavLink components in my navbar, the url changes and the page routes correctly, BUT, the scroll bar is missing and I can't scroll the page. However if I manually refresh the page in the browser, the scroll bar is back again and everything works as expected. Also, this doesn't happen on all of my NavLinks, only some of them. For instance, the Login and Register NavLinks render with the scrollbar, as well as my About page inside my Footer component. I have checked to see if there are any differences in the structuring of the Routes or the NavLink components, but I couldn't see any differences.
I have tried automatically refreshing the page once with useEffect, but I can't get it to refresh only once, it keeps refreshing in a loop, so I removed it...
ANY HELP WOULD BE HIGHLY APPRECIATED...
Here is my App.jsx:
function App() {
const { pathname } = useLocation();
useEffect(() => {
window.scrollTo(0, 0);
}, [pathname]);
return (
<div className="App">
<Navbar />
<div id="back-to-top-anchor" style={{ minHeight: "0" }}></div>
<ParallaxProvider>
<Routes>
<Route path="/" element={<Home />} />
<Route path="about" element={<About />} />
<Route
path="all-listings"
element={<AllListings initialState={initialState} />}
/>
<Route
path="listing/:listingId"
element={<Listing initialState={initialState} />}
/>
<Route path="how-it-works" element={<HowItWorks />} />
<Route path="contact-us" element={<ContactUs />} />
<Route path="login" element={<Login />} />
<Route path="register" element={<Register />} />
<Route path="*" element={<ErrorPage />} />
<Route path="my-listings" element={<MyListings />} />
</Routes>
</ParallaxProvider>
<ShapeDivider color="#ffffff">
<Footer />
</ShapeDivider>
</div>
);
}
And here is my menu inside NavBar.jsx:
const menu = (
<>
<div
onClick={() => {
setMobileOpen(true);
}}
className={classes.navbarSmallMenu}
>
<NavLink
className={({ isActive }) =>
isActive ? classes.activeNavbarStyle : undefined
}
to="/"
>
Home
</NavLink>
<NavLink
className={({ isActive }) =>
isActive ? classes.activeNavbarStyle : undefined
}
to="all-listings"
>
All Listings
</NavLink>
<NavLink
className={({ isActive }) =>
isActive ? classes.activeNavbarStyle : undefined
}
to="how-it-works"
>
How It Works
</NavLink>
<NavLink
className={({ isActive }) =>
isActive ? classes.activeNavbarStyle : undefined
}
to="contact-us"
>
Contact Us
</NavLink>
</div>
<div className={classes.navbarSmallMenu}>
{isUserLoggedIn ? (
<>
<IconButton
id="profile-avatar"
onClick={handleOpenUserMenu}
sx={{ p: 0 }}
>
<Avatar alt="User Profile" />
</IconButton>
<Menu
className={classes.profileMenu}
id="menu-appbar"
anchorEl={anchorUser}
anchorOrigin={{
vertical: "top",
horizontal: "right",
}}
keepMounted
transformOrigin={{
vertical: "top",
horizontal: "right",
}}
open={Boolean(anchorUser)}
onClose={handleCloseUserMenu}
>
<NavLink
className={({ isActive }) =>
isActive ? classes.activeNavbarStyle : undefined
}
to="/"
>
Show Profile
</NavLink>
<ul>
<li>
<NavLink
className={({ isActive }) =>
isActive ? classes.activeNavbarStyle : undefined
}
to="my-listings"
>
My Listings
</NavLink>
</li>
<li>Pages</li>
<li>Goes</li>
<li>Here</li>
<li
className={classes.logOutButton}
onClick={() => {
localStorage.clear();
navigate(0);
}}
>
Log Out
</li>
</ul>
</Menu>
</>
) : (
<>
<NavLink
className={({ isActive }) =>
isActive ? classes.activeNavbarStyle : undefined
}
to="login"
>
Login
</NavLink>
<NavLink
className={({ isActive }) =>
isActive ? classes.activeNavbarStyle : undefined
}
to="register"
>
Register
</NavLink>
</>
)}
</div>
</>
);```
Related
I'm just starting to use material ui and having a hard time trying to style the active list item of a sidebar menu. Here's what I've tried so far. What am I missing or doing wrong?
<>
<ListItemButton onClick={i.onClick}>
<Icon/>
<ListItemText primary={i.listItemText} />
</ListItemButton>
<Collapse in={open} timeout='auto' unmountOnExit>
<List component='div' disablePadding>
{i.nestedItems?.map((n, idx) => (
<ListItemButton sx={{ pl: '4.3rem' }}>
<ListItemText
primary={i.nestedItems[idx]}
/>
</ListItemButton>
))}
</List>
</Collapse>
</>
))}
I've tried styling it in them theme like som but it doesn't work:
styleOverrides: {
root: {
"&:focus": {
fontWeight: baseTheme.typography.fontWeightBold
},
},
},
}
I am making a Navbar for my dashboard but encountered this error which says I should pass a string to className and not function . I am passing the function to className as I have to check if the navbar is open or not. How can I solve this error?
Here is my code for navbar:
//STYLES
import styles from "./Navbar.module.scss";
import React from 'react';
//CONTEXT
import { useContext } from "react";
import NavContext from "../../context/NavContext";
//REACT ROUTER
import { NavLink } from "react-router-dom";
//ICONS
import {
MdOutlineDashboard,
MdOutlineAnalytics,
MdOutlinedFlag,
MdPeopleOutline,
MdOutlineMessage,
MdOutlineLogout,
} from "react-icons/md";
import { FaTimes } from "react-icons/fa";
import { BsThreeDots } from "react-icons/bs";
import { VscDashboard } from "react-icons/vsc";
const NavUrl = ({ url, icon, description }) => {
const { nav, setNav } = useContext(NavContext);
const checkWindowSize = () => {
if (window.innerWidth < 1024) setNav(!nav);
};
return (
<li className={styles.li_navlink}>
<NavLink
to={`${url}`}
className={({ isActive }) => (isActive ? styles.active : undefined)}
onClick={() => checkWindowSize()}
>
{icon}
<span className={styles.description}>{description}</span>
</NavLink>
</li>
);
};
const Navbar = () => {
const { nav, setNav } = useContext(NavContext);
return (
<div
className={`${styles.navbar_container} ${
nav ? styles.navbar_mobile_active : undefined
}`}
>
<nav className={nav ? undefined : styles.nav_small}>
{/* LOGO */}
<div className={styles.logo}>
<VscDashboard className={styles.logo_icon} />
<FaTimes
className={styles.mobile_cancel_icon}
onClick={() => {
setNav(!nav);
}}
/>
</div>
{/* MENU */}
<ul className={styles.menu_container}>
{/* FIRST CATEGORY */}
<span className={styles.categories}>
{nav ? "Pages" : <BsThreeDots />}
</span>
<NavUrl
url="/"
icon={<MdOutlineDashboard />}
description="Dashboard"
/>
<NavUrl
url="usage"
icon={<MdOutlineAnalytics />}
description="Usage"
/>
<NavUrl
url="plan"
icon={<MdOutlinedFlag />}
description="Plan"
/>
<NavUrl url="documentation" icon={<MdPeopleOutline />} description="Documentation" />
<NavUrl
url="invoices"
icon={<MdOutlineMessage />}
description="Invoices"
/>
</ul>
{/* LOGOUT BUTTON */}
<div
className={`${styles.btn_logout}`}
onClick={() => {
setNav(!nav);
}}
>
<MdOutlineLogout />
</div>
</nav>
<div
className={nav ? styles.mobile_nav_background_active : undefined}
onClick={() => {
setNav(!nav);
}}
></div>
</div>
);
};
export default Navbar;
Here is my error which is saying to pass string in navlink , navurl ,ul , nav , navbar , div , App , route , switch , router , browserRouter classes :
index.js:1 Warning: Failed prop type: Invalid prop `className` of type
`function` supplied to `NavLink`, expected `string`.
in NavLink (at Navbar.jsx:33)
in NavUrl (at Navbar.jsx:73)
in ul (at Navbar.jsx:67)
in nav (at Navbar.jsx:54)
in div (at Navbar.jsx:49)
in Navbar (at App.jsx:24)
in div (at App.jsx:21)
in App (at src/index.js:19)
in Route (at src/index.js:19)
in Switch (at src/index.js:18)
in Router (created by BrowserRouter)
in BrowserRouter (at src/index.js:17)
I think you do it in the last div you have
<div
className={nav ? styles.mobile_nav_background_active : undefined}
onClick={() => {
setNav(!nav);
}}
></div>
may be you must use onMouseEnter
onMouseEnter={() => {
setisActive (true);
}}
onMouseLeave={() => {
setisActive (false);
}}
className={isActive ? styles.active : undefined}
I am trying to style my material UI tabs in my react component but I can seem to get them applied correctly. How can I do so?
I would like to set the background color and box shadow of the entire bar, and and indicator background color and underline for the active tab. Thank you!
Here's what I have so far:
const routes = ["/tab1", "/tab2"];
function MainNavigation() {
const styles = {
backgroundColor: "white",
boxShadow: '0 2px 2px -2px rgba(0,0,0,.2)'
};
return (
<IonToolbar >
<BrowserRouter >
<Route
path="/"
render={(history) => (
<div className="toolbar">
<Tabs
TabIndicatorProps={{style: {background:'primary'}}}
indicatorColor="primary"
color="primary"
variant="scrollable"
scrollButtons="auto"
aria-label="scrollable auto tabs"
value={history.location.pathname !== "/" ? history.location.pathname : false}
>
<Tab className="mat-tab"
label="Tab1"
value={routes[1]}
component={Link}
to={routes[1]}
></Tab>
<Tab className="mat-tab"
label="Tab2"
value={routes[0]}
component={Link}
to={routes[0]}
></Tab>
</Tabs>
</div>
)}
></Route>
<Switch >
<Route path="/scutes" component={Tab2}></Route>
<Route path="/gateways" component={Tab1}></Route>
<Redirect exact from="/" to="/tab2" />
</Switch>
</BrowserRouter>
</IonToolbar>
);
}
export default MainNavigation;
function handleTabChange(index: any) {
throw new Error("Function not implemented.");
}
Import styled
import styled from "styled-components";
declare your styles
const NewTab = styled(Tab)`
font-size: 100px;
`
Use new element instead of default Tab
import styled from "styled-components";
const routes = ["/tab1", "/tab2"];
const NewTab = styled(Tab)`
font-size: 100px;
`
function MainNavigation() {
const styles = {
backgroundColor: "white",
boxShadow: '0 2px 2px -2px rgba(0,0,0,.2)'
};
return (
<IonToolbar >
<BrowserRouter >
<Route
path="/"
render={(history) => (
<div className="toolbar">
<Tabs
TabIndicatorProps={{style: {background:'primary'}}}
indicatorColor="primary"
color="primary"
variant="scrollable"
scrollButtons="auto"
aria-label="scrollable auto tabs"
value={history.location.pathname !== "/" ? history.location.pathname : false}
>
<NewTab className="mat-tab"
label="Tab1"
value={routes[1]}
component={Link}
to={routes[1]}
></NewTab>
<NewTab className="mat-tab"
label="Tab2"
value={routes[0]}
component={Link}
to={routes[0]}
></NewTab>
</Tabs>
</div>
)}
></Route>
<Switch >
<Route path="/scutes" component={Tab2}></Route>
<Route path="/gateways" component={Tab1}></Route>
<Redirect exact from="/" to="/tab2" />
</Switch>
</BrowserRouter>
</IonToolbar>
);
}
export default MainNavigation;
function handleTabChange(index: any) {
throw new Error("Function not implemented.");
}
i have written a static sidebar which every icon opens a "sub-sidebar" onclick. i handle the switches between the differrent "sub-sidebars" with react-states.
but i didnĀ“t get to manage that the sub-sidebar closes when a icon is clicked a second time. Anyone an idea how to do this? Thanks in advance.
import React, { Component } from 'react';
import { GrAdd, BsCollection, IoSettingsOutline } from '../icons';
import New from './sidebars/new';
import Collection from './sidebars/collection';
import Settings from './sidebars/settings';
import '../css/StaticBar.css'
class StaticBar extends Component {
constructor(props) {
super(props)
this.state = {
selected: 0,
}
}
render() {
return (
<div className="StaticBar">
<ul>
<li className="ListItem" onClick={() => this.setState({ selected: 0 })}>
<GrAdd color="white"/>
</li>
<li className="ListItem" onClick={() => this.setState({ selected: 1 })}>
<BsCollection color="white" />
</li>
<li className="ListItem" onClick={() => this.setState({ selected: 2 })}>
<IoSettingsOutline color="white" />
</li>
</ul>
{(this.state.selected === 0) && <New />}
{(this.state.selected === 1) && <Collection />}
{(this.state.selected === 2) && <Settings />}
</div>
);
}
}
export default StaticBar;
You can use this conditional setState logic
import React, { Component } from 'react';
import { GrAdd, BsCollection, IoSettingsOutline } from '../icons';
import New from './sidebars/new';
import Collection from './sidebars/collection';
import Settings from './sidebars/settings';
import '../css/StaticBar.css'
class StaticBar extends Component {
constructor(props) {
super(props)
this.state = {
selected: 0,
}
}
render() {
return (
<div className="StaticBar">
<ul>
<li className="ListItem" onClick={() => this.setState({ selected: 0 })}>
<GrAdd color="white"/>
</li>
<li className="ListItem" onClick={() => this.setState({ selected: (this.state.selected==1 ? 0 : 1) })}>
<BsCollection color="white" />
</li>
<li className="ListItem" onClick={() => this.setState({ selected: ( this.state.selected==2 ? 0 : 2) })}>
<IoSettingsOutline color="white" />
</li>
</ul>
{(this.state.selected === 0) && <New />}
{(this.state.selected === 1) && <Collection />}
{(this.state.selected === 2) && <Settings />}
</div>
);
}
}
export default StaticBar;
I want to display dynamic content in Sidebar.Pusher based on the item clicked from the menu. Here is my code -
<Sidebar.Pushable >
<Sidebar as={Menu} animation='push' width='thin' visible={visible} icon='labeled' vertical inverted>
<Menu.Item name='home' >
<Icon name='tasks' />
Manage categories
</Menu.Item>
<Menu.Item name='home' >
<Icon name='tasks' />
Manage products
</Menu.Item>
</Sidebar>
<Sidebar.Pusher >
<Segment basic>
Display Dynamic content
</Segment>
</Sidebar.Pusher>
Any leads will be highly appreciated.
If I understand the question correctly, there are a few possible solutions. In one of my projects I'm using it with React Router, so in the <Sidebar /> component I have <Menu.Item as={Link} to='/path' /> and then the <Route path='/path' /> is in a <Switch /> statement in <Sidebar.Pusher />.
If you want to change rendered components without React Router, here is an example of how I implemented it.
import React, { Component } from 'react'
import { Sidebar, Segment, Menu } from 'semantic-ui-react'
export default class SideNav extends Component {
constructor(props) {
super(props)
this.state = {
renderTab: 'home'
}
}
changeTab(tabName) {
this.setState({ renderTab: tabName })
}
render() {
const { renderTab } = this.state
return (
<Sidebar.Pushable as={Segment}>
<Sidebar as={Menu} visible vertical>
<Menu.Item onClick={() => this.changeTab('home')} as='a' name='home'>
Home
</Menu.Item>
<Menu.Item onClick={() => this.changeTab('about')} as='a' name='about'>
About
</Menu.Item>
</Sidebar>
<Sidebar.Pusher>
<RenderedContent tabName={renderTab} />
</Sidebar.Pusher>
</Sidebar.Pushable>
)
}
}
const RenderedContent = ({ tabName }) => {
if (tabName === 'home') {
return <Home />
}
if (tabName === 'about') {
return <About />
}
}
const Home = () => (
<div>This is the home page</div>
)
const About = () => (
<div>This is the about page</div>
)