I am new to ReactJS and have an issue with using "Menu.Item" (from Semantic UI React) and React Router.
My imports etc will be left out of the below code but they are all working fine.
My "App.jsx" constructor is as follows:
constructor(props) {
super(props);
this.state = {
activeItem: 'home',
loading: true,
messages: [],
};
}
The "App.jsx" render return is this:
<Router>
<Container className="main">
<Navbar
onItemClick={selected => this.setState({ activeItem: selected })}
isActive={this.state.activeItem}
/>
<Container className="main-content">
<Switch>
<Route exact path="/" component={Home} />
<Route path="/dashboard" component={Dashboard} />
<Route path="/user" component={User} />
</Switch>
</Container>
</Container>
</Router>
For clarification, the Home, User, and Dashboard components are just simple Div's that has their respective names in them.
My Navbar is as follows:
class Navbar extends Component {
onItemChange = (e, { name }) => this.props.onItemClick(name);
render() {
return (
<div>
<Container>
<Menu secondary stackable widths={4}>
<Menu.Item>
<img src={Logo} alt="header" />
</Menu.Item>
<Menu.Item
as={NavLink}
to="/"
name="home"
active={this.props.isActive === 'home'}
onClick={(event, name) => this.handleClick(name.name, name.to)}
>
<Icon name="home" size="large" />
<p>Home</p>
</Menu.Item>
<Menu.Item
as={NavLink}
to="/dashboard"
name="Data"
active={this.props.isActive === 'Data'}
onClick={this.onItemChange}
>
<Icon name="dashboard" size="large" />
<p>Dashboard</p>
</Menu.Item>
<Menu.Item
as={NavLink}
to="/user"
name="user"
active={this.props.isActive === 'user'}
onClick={this.onItemChange}
>
<Icon name="user" size="large" />
<p>User</p>
</Menu.Item>
</Menu>
</Container>
</div>
);
}
}
As you can see from the above Navbar, I am using NavLink within the Menu.Item.
Here is where the issue arises. When I start my application it works fine, 'home' is displayed, however when I click on a link in the Menu, the application crashes.
Any ideas on how to fix this? I also want to have it that the 'isActive' will update with the current route in the menu.
Any input would be greatly appreciated.
I fixed it for anyone looking into it by simplifying the code, here is the Navbar component:
const Navbar = () => (
<div>
<Container>
<Menu secondary stackable widths={4}>
<Menu.Item>
<img src={Logo} alt="header" />
</Menu.Item>
<Menu.Item as={NavLink} to="/" name="home">
<Icon name="home" size="large" />
<p>Home</p>
</Menu.Item>
<Menu.Item as={NavLink} to="/data" name="data">
<Icon name="dashboard" size="large" />
<p>Dashboard</p>
</Menu.Item>
<Menu.Item as={NavLink} to="/user" name="user">
<Icon name="user" size="large" />
<p>User</p>
</Menu.Item>
</Menu>
</Container>
</div>
);
Less does more, it seems. Hope this helps anyone.
Related
I'm working on react website and I have a problem while navigating to any page
that when I scroll to a certain point in a home page for example then I try to navigate to another page I find the other page is rendered from the the bottom of the page not the top
routes.tsx file
const App: React.FC = () => (
<BrowserRouter>
<Layout className="layout">
<div style={{ marginBottom: "64px" }}>
<Header>
<AppHeader />
</Header>
</div>
<Content>
<div className="site-layout-content">
<Routes>
<Route path="/" element={<Home />} />
<Route path="/offers" element={<Login />} />
<Route path="/aboutUs" element={<AboutUs />} />
<Route path="/contactUs" element={<ContactUs />} />
<Route path="/placeDetails/:id" element={<PlaceDetails />} />
<Route path="/advantages" element={<Advantages />} />
</Routes>
</div>
</Content>
<Footer style={{ textAlign: "center" }}>
<AppFooter />
</Footer>
</Layout>
</BrowserRouter>
);
export default App;
header.tsx
const Index = () => {
const navigate = useNavigate();
return (
<Row className="header">
<Col span={12} className="header__logo">
<div className="header__logo--imgContainer" onClick={() => navigate("/")}>
<img src={logoImg} alt="logo" />
</div>
</Col>
<Col span={12} className="header__menu">
<ul className="ant-menu-overflow ant-menu ant-menu-root ant-menu-horizontal ant-menu-light ant-menu-rtl">
<li className="ant-menu-item">
<span onClick={() => navigate("/offers")}>{strings.header.offers}</span>
</li>
<li className="ant-menu-item">
<span onClick={() => navigate("/advantages")}>{strings.header.services}</span>
</li>
</ul>
</Col>
</Row>
);
};
export default Index;
you can simply use this helper component for this use case:
import { useEffect } from "react";
import { useLocation } from "react-router-dom";
export default function ScrollToTop() {
const { pathname } = useLocation();
useEffect(() => {
// "document.documentElement.scrollTo" is the magic for React Router Dom v6
document.documentElement.scrollTo({
top: 0,
left: 0,
behavior: "instant", // Optional if you want to skip the scrolling animation
});
}, [pathname]);
return null;
}
and then you can change above code like this:
const App: React.FC = () => (
<BrowserRouter>
<ScrollToTop/> // this is new helper component
<Layout className="layout">
<div style={{ marginBottom: "64px" }}>
<Header>
<AppHeader />
</Header>
</div>
<Content>
<div className="site-layout-content">
<Routes>
<Route path="/" element={<Home />} />
<Route path="/offers" element={<Login />} />
<Route path="/aboutUs" element={<AboutUs />} />
<Route path="/contactUs" element={<ContactUs />} />
<Route path="/placeDetails/:id" element={<PlaceDetails />} />
<Route path="/advantages" element={<Advantages />} />
</Routes>
</div>
</Content>
<Footer style={{ textAlign: "center" }}>
<AppFooter />
</Footer>
</Layout>
</BrowserRouter>
);
export default App;
This will reset the scroll position on top whenever route changes.
I am creating a project using React and ant design. I have created the navbar but it is not getting rendered properly. I am able to select an option but I cannot deselect it (like shown in the image, the project is in the initial stage so everything is a little misaligned). You can view the site here: http://192.168.56.1:3000/ .I am providing the code for app.js and navbar.jsx
App.js:
const App = () => {
return (
<div className="app">
<div className="navbar">
<Navbar />
</div>
<div className="main">
<Layout>
<div className="routes">
<Switch>
<Route exact path="/">
<Homepage />
</Route>
<Route exact path="/cryptocurrencies">
<Cryptocurrencies />
</Route>
<Route exact path="/exchanges">
<Exchanges />
</Route>
<Route exact path="/news">
<News />
</Route>
<Route exact path="/crypto/:coinId">
<CryptoDetails />
</Route>
</Switch>
</div>
</Layout>
<div className="footer">
<Typography.Title level={5} style={{ color: 'white', textAlign: 'center' }}>
Krypton <br />
All rights reserved
</Typography.Title>
<Space>
<Link to="/">Home</Link>
<Link to="/exchanges">Exchanges</Link>
<Link to="/news">News</Link>
</Space>
</div>
</div>
</div>
);
}
Navbar.jsx:
const Navbar = () => {
return (
<div className="nav-container">
<div className="logo-container">
<Avatar src={icon} size="large" />
<Typography.Title level={2} className="logo">
<Link to="/">Krypton</Link>
</Typography.Title>
{/* <Button className="menu-control-container">
</Button> */}
</div>
<Menu theme="dark">
<Menu.Item icon={<HomeOutlined />}>
<Link to="/">Home</Link>
</Menu.Item>
</Menu>
<Menu theme="dark">
<Menu.Item icon={<FundOutlined />}>
<Link to="/cryptocurrencies">Cryptocurrencies</Link>
</Menu.Item>
</Menu>
<Menu theme="dark">
<Menu.Item icon={<MoneyCollectOutlined />}>
<Link to="/exchanges">Exchanges</Link>
</Menu.Item>
</Menu>
<Menu theme="dark">
<Menu.Item icon={<BulbOutlined />}>
<Link to="/news">News</Link>
</Menu.Item>
</Menu>
</div>
);
}
After updated a bunch of our dependencies we are now are forced to use anchor tags which causes redirects, before we used but now everytime we click on a it goes to the proper url ie /screens but is just a blank page and never presents the components, below is our parent index.tsx file:
ReactDOM.render(
<Provider {...stores}>
{/* Changed routes to children */}
{/* <Router children={routes} history={createHistory} /> */}
<Router history={createHistory}>
<div>
<Switch>
<Route path='/oauth2callback' componentDidMount={console.log()}>
{() => {
if(window.location.href.includes('/oauth2callback'))
{
oauth2callback(window.location.hash)
}
}}
</Route>
<Route path='/testing' component={Get} />
<Route path='/'>
{/* Function that determines if the user is logged in and can allow the authenticated passage or not. If no, it will not render authenticated pages*/}
{() => {
if(auth.loggedIn())
{
console.log("is logged in")
return(
<div>
<Route component={App} history={createHistory}/>
<div className="row" id="wrapper">
<Switch>
{/* <Route path='/screens' component={Screens}/> */}
<Route path='/screens' component={Screens}/>
<Route path='/playlists' component={Playlists}/>
<Route path='/content' component={Content}/>
<Route path='/help' component={HelpNav}/>
<Route component={NotFound}/>
</Switch>
</div>
</div>
)
}
else
{
console.log("is not logged in")
return(
<Route path='/' component={HomeNav}/>
)
}
}}
</Route>
<Route path='401' component={Get} />
</Switch>
</div>
</Router>
</Provider>,
and here is the app.tsx with the navbar:
<Nav className="mb-nav">
{/* <IndexLinkContainer to="/screens"> */}
<Nav.Item style={{width: widthConstants[0]}}>
<Link to='/screens' style={{color: this.state.navIndex === 0 ? "white" : "bbddba"}}>
Screens
</Link>
</Nav.Item>
{/* </IndexLinkContainer> */}
{/* <LinkContainer to="/playlists"> */}
<Nav.Item style={{width: widthConstants[1]}}>
<a href="/playlists" style={{color: this.state.navIndex === 1 ? "white" : "bbddba"}}>
Playlists
</a>
</Nav.Item>
{/* </LinkContainer> */}
{/* <LinkContainer to="/content"> */}
<Nav.Item style={{width: widthConstants[2]}}>
<a href="/content" style={{color: this.state.navIndex === 2 ? "white" : "bbddba"}}>
Content
</a>
</Nav.Item>
{/* </LinkContainer> */}
{/* <LinkContainer to="/help"> */}
<Nav.Item style={{width: widthConstants[3]}}>
<a href="/help" style={{color: this.state.navIndex === 3 ? "white" : "bbddba"}}>
Help
</a>
</Nav.Item>
{/* </LinkContainer> */}
{this.shouldRenderTouch && <TouchButton/>}
</Nav>
</Navbar.Collapse>
</div>
</Navbar>
any idea what is different in the new react router update to cause this bug to exist?
The fix was much simpler than I thought, the new update integrated BrowserRouter instead of the Router so I replaced
<Router history={createHistory}>
with
<BrowserRouter>
and everything is now working as it should
Read "Routes and Links are relative to their parent" on this React Router 6 article
https://medium.com/frontend-digest/whats-new-in-react-router-6-732b06cc83e4
by the way it's strange that you have <a> tags instead of Link components sometimes
I have a problem with react-router. This is my /home component, the first page you see after logging in:
return(
<>
<CustomNavbar />
<Container fluid>
{ loading ? (
<div>Loading...</div>
) : (
<Router>
<ProtectedRoute
path='/home/mem'
render={(props) => <MResult
{...props}
data={data}
users={users} />
}
/>
<ProtectedRoute
path='/home/reading'
render={(props) => <RResult
{...props}
data={readingData}
users={users} />
}
/>
</Router>
)}
</Container>
</>
)
I have a table and I need to display different data based on the second part of the url (I'm using my own component ProtectedRoute to check for authentication, but the behaviour is the same we the usual Route component).
In the CustomNavbar component I have two links:
return(
<Navbar bg="primary" variant="dark">
<Navbar.Brand className='cursor-default'>
<span style={{marginLeft: "10px"}}></span>
</Navbar.Brand>
<Navbar.Toggle />
<Navbar.Collapse>
{ props.authenticated && (
<>
<Button>
<Link to="/home/reading">Reading</Link>
</Button>
<Button>
<Link to="/home/mem">MemResult</Link>
</Button>
</>
)}
</Navbar.Collapse>
<Navbar.Collapse className='justify-content-end'>
{ props.authenticated && (
<Button onClick={logout}>logout</Button>
)}
</Navbar.Collapse>
</Navbar>
)
The problem is that if I click on the links in the navbar I can see the url changing accordingly, but the new component is not being loaded, I still see the previous one. If I hit the browser's refresh button, then the correct component is loaded, but once that happened, again, clicking on the links won't change a thing but the url.
How can I fix this?
The CustomNavbar component is outside of the Router provider which is why Links aren't able to communicate to the Route component.
The solution is to render Router component at the top level and render CustomNavbar as a default route
return(
<Router>
<Route component={CustomNavbar} />
<Container fluid>
{ loading ? (
<div>Loading...</div>
) : (
<ProtectedRoute
path='/home/mem'
render={(props) => <MResult
{...props}
data={data}
users={users} />
}
/>
<ProtectedRoute
path='/home/reading'
render={(props) => <RResult
{...props}
data={readingData}
users={users} />
}
/>
</Router>
)}
</Container>
</Router>
)
Not really sure I'm doing wrong here. I have a header component which I am then using in my main app component where my "page" components are conditionally rendered based on the app. Manually going to the routes works, however React Router's Link component is not rendering the links as clickable buttons thus I can't click on anything...
Here is my header component:
function Header(props) {
const links = props.links.map(link => {
return (
<Link to={{pathname: link.path}} key={link.title}>{link.title}</Link>
);
});
return(
<Navbar className="border-bottom" bg="transparent" expand="lg">
<Navbar.Brand href="#home">Garrett Love</Navbar.Brand>
<Navbar.Toggle className="border-0" aria-controls="basic-navbar-nav" />
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="ml-auto">
{links}
</Nav>
</Navbar.Collapse>
</Navbar>
);
}
I did try setting the to prop as both to={link.path} and to="/about" but neither worked.
I'm just putting this component in my main app component like so:
render() {
return(
<Router>
<Container className="p-0" fluid={true}>
<Header links={this.state.headerLinks} />
<Route path="/" exact render={() => <Home title={this.state.home.title} subTitle={this.state.home.subTitle} />} />
<Route path="/about" render={() => <About title={this.state.about.title} />} />
<Footer />
</Container>
</Router>
);
}
I see you has header component and some app component
But in your app component you show <Gbar /> and dont show <Header />
The best way to fix this:
In Header
const Header = props =>
<Navbar className="border-bottom" bg="transparent" expand="lg">
<Navbar.Brand href="#home">Garrett Love</Navbar.Brand>
<Navbar.Toggle className="border-0" aria-controls="basic-navbar-nav" />
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="ml-auto">
{props.links.map(link => <Link to={link.path} key={link.title}>{link.title}</Link>)}
</Nav>
</Navbar.Collapse>
</Navbar>
And in App:
render() {
return(
<Router>
<Container className="p-0" fluid={true}>
<Header links={this.state.headerLinks} />
<Route path="/" exact render={() => <Home title={this.state.home.title} subTitle={this.state.home.subTitle} />} />
<Route path="/about" render={() => <About title={this.state.about.title} />} />
<Footer />
</Container>
</Router>
);
}