Nav Menu Active Element and State Management Issue - javascript

I am trying to show an active <Nav.Link> element for the current page, but it keeps getting reset when I go between pages to the default value. Each of the links goes to a different route I have defined in React-Router. I am trying to use jotai for state management to store the value of the current page, but am not able to get the correct value to display.
For example, the code below has pills to show the active selection in the nav. I want to be able to do this even when I go to a different page since this is the nav menu.
import Nav from 'react-bootstrap/Nav';
function TabsExample() {
return (
<Nav variant="pills" defaultActiveKey="/home">
<Nav.Item>
<Nav.Link href="/home">Active</Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link eventKey="link-1">Option 2</Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link eventKey="disabled" disabled>
Disabled
</Nav.Link>
</Nav.Item>
</Nav>
);
}
export default TabsExample;
However, I believe my page keeps re-rendering/reloading (goes white for a brief second) for some reason whenever I go to a different page.
There might be something I'm not getting, so please let me know.

The issue here is likely that the Nav.Link component renders an anchor <a> element by default and this is causing the page to reload when you click the links. You can specify each Nav.Link to render the NavLink (or Link) component exported from react-router-dom so that clicking links will now correctly be handled by RRD. Specify a to prop instead of an href prop, and set the eventKey prop to match the link target so the "pill" state can work as well.
Example:
import { NavLink } from "react-router-dom";
import "bootstrap/dist/css/bootstrap.min.css";
import Nav from "react-bootstrap/Nav";
function PillsExample() {
return (
<Nav variant="pills">
<Nav.Item>
<Nav.Link as={NavLink} end to="/" eventKey="/"> // * Note on end prop
Home
</Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link as={NavLink} to="/foo" eventKey="/foo">
Foo
</Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link as={NavLink} to="/bar" eventKey="/bar">
Bar
</Nav.Link>
</Nav.Item>
</Nav>
);
}
* Note: If the end prop is used, it will ensure this component isn't matched as "active" when its descendant paths are matched. See NavLink for more component details.

Related

React Bootstrap: preserve current tab on page reload

The question has been asked many times before, but never for React Bootstrap: how do you preserve the active tab on page reload? In other words, when a user clicks a tab in the navbar, it is easy to add a hash to the current page URL. However, when the page is reloaded, the eventKey is not consistent with the URL. I've scoured the following RB docs and haven't found a prop intended for this purpose:
https://react-bootstrap.github.io/components/navs/#tabs
https://react-bootstrap.github.io/components/tabs/#tab-container-props
Here is my code:
<Card className="m-auto w-100 w-xl-75">
<Tab.Container id="tabs">
<Card.Header>
<Nav variant="tabs">
<Nav.Item>
<Nav.Link href="#licenses" style={{ outline: 'none' }}>Licenses</Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link href="#releases" style={{ outline: 'none' }}>Releases</Nav.Link>
</Nav.Item>
</Nav>
</Card.Header>
<Card.Body>
<Tab.Content>
<Tab.Pane eventKey="licenses" id="licenses">
<Licenses licenses={licenses} />
</Tab.Pane>
<Tab.Pane eventKey="releases" id="releases">
<Releases releases={releases} />
</Tab.Pane>
</Tab.Content>
</Card.Body>
</Tab.Container>
</Card>
I'm not pretty sure if I understand your question, but given the context, I would suggest that you store the user's currently selected tab in one of the caches, sessions of the frontend.
For example,
By using session storage:
You could store your selected key on the following way:
const storeSelection = (selection) => localStorage.setItem('tabSelection', selection);
<Nav.Item>
<Nav.Link href="#licenses" style={{ outline: 'none' }} onSelect={{this.storeSelection('licenses')}}>Licenses</Nav.Link>
</Nav.Item>
Then, you can just select that tab onComponentDidMount or just any other place you prefer.
I'm assuming that this state that you want to store is more of a state that you want to keep on the frontend side.

react bootstrap dropdown doesn't close when react router link gets called

<NavDropdown
className="userDropdownButton"
title="dropdown"
id="user-nav-dropdown"
alignRight
>
<div className="userDropDown">
<Link to="/user" className="userDropDownheader">
user
</Link>
</div>
</NavDropdown>
And both - the dropdown and the <Link> work just fine, but the dropdown doesn't close when I click on the link. I tried using https://github.com/react-bootstrap/react-router-bootstrap but it didn't fix my issue. Are there some other things I could try?
npm install react-router-bootstrap
then in your nav page :
import { LinkContainer } from "react-router-bootstrap";
<NavDropdown title='Dropdown' id='responsive-navbar-nav'>
<LinkContainer to='/views/Page4' >
<NavDropdown.Item>Counter</NavDropdown.Item>
</LinkContainer>
</NavDropdown>
Im using https://react-bootstrap.github.io/components/navbar/
Hope you can use LinkContainer to solve your problem.

React Bootstrap Navbar hanging computer

I am facing a issue with my react bootstrap code. Whenever I use Navbar component of react bootstrap, my computer gets hang and I had to force shutdown computer. I am not sure what exactly wrong with the code snippet below:
import React, { Component } from 'react';
import Nav from 'react-bootstrap/Nav';
import './navbar.css';
class Navbar extends Component {
render() {
return (
<div className="nav-container">
<Navbar bg="dark" variant="dark">
<Nav className="mr-auto">
<Nav.Link href="#home">Home</Nav.Link>
<Nav.Link href="#features">Features</Nav.Link>
<Nav.Link href="#pricing">Pricing</Nav.Link>
</Nav>
</Navbar>
</div>
)
}
}
export default Navbar;
Interesting thing is whenever I use plain html to render Navbar computer does not hang but when I had this react bootstrap Navbar, it hangs.
You defined a component called Navbar and you're calling it inside itself. Seems like that would create a vicious loop that will kill your App and by extension your computer performance.
Try renaming the component to something else or take out the Navbar jsx inside your render which doesnt seem necessary:
import React, { Component } from 'react';
import Nav from 'react-bootstrap/Nav';
import './navbar.css';
class Navbar extends Component {
render() {
return (
<div className="nav-container">
<Nav className="mr-auto">
<Nav.Link href="#home">Home</Nav.Link>
<Nav.Link href="#features">Features</Nav.Link>
<Nav.Link href="#pricing">Pricing</Nav.Link>
</Nav>
</div>
)
}
}
export default Navbar;
See working sandbox: https://codesandbox.io/s/shy-hooks-e6n81

Warning: validateDOMNesting(...): <a> cannot appear as a descendant of <a>

I'm trying to use react-router with reactstrap with create-react-app.
In the routing page, I needed to use state for the reactstrap, so I converted the router from a variable to a class, but I get this warning:
Warning: validateDOMNesting(...): <a> cannot appear as a descendant of <a>.
I don't know what to do. I needed to style the router navigation using reactstrap, so I did this:
<NavLink
componentClass={Link}
href="/contact"
to="/contact"
active={location.pathname === '/contact'}
>
anywords
</NavLink>
<Navbar dark id="RouterNavbar" expand="md">
<NavbarBrand id="NavBrand"href="#x">
<ul>
{/* a bunch of <li></li> */}
</ul>
</NavbarBrand>
<NavbarToggler id="NavBarToggler" onClick={this.toggle1.bind(this)} />
<Collapse isOpen={this.state.isOpen1} navbar>
<Nav className="ml-auto" navbar>
<NavItem>
<NavLink href="#x"><Link id="RouterNavLink" style={None} to="/contact">anywords</Link></NavLink>
</NavItem>
{/* just more of the above */}
Other than a couple of <li> coming close to each other at random times, hot reloading not working sometimes, and the warning message I get in the console, nothing bad happens, but when I read about this issue, I found out that I shouldn't do this.
This is the code which causing the error,
<NavLink href="#x"><Link id="RouterNavLink" style={None} to="/contact">anywords</Link></NavLink>
Which is converted to,
<a><a></a></a>
So you are getting error,
Warning: validateDOMNesting(…): <a> cannot appear as a descendant of <a>
To solve this just use one of the follow,
<NavLink id="RouterNavLink" style={None} to="/contact">anywords</NavLink>
OR,
<Link id="RouterNavLink" style={None} to="/contact">anywords</Link>
Add the as prop (formerly componentClass) to your original NavLink to keep the styling while also silencing the warning.
See react-bootstrap#nav-link-props docs
Or View Screenshot
Original:
<NavLink href="#x">
<Link id="RouterNavLink" style={None} to="/contact">anywords</Link>
</NavLink>
New:
<Nav.Link as={Link} to="/contact">anywords</Nav.Link>
I would like to suggest an alternate solution which not only solve your problem but give you desired result. In any case someone else stumbled on this post like I did.
Use Link jsx element offered by react router dom but add className="nav-link" to it. This will give you styling of the NavLink jsx which react strap is using.
So, it should look like this,
<Link className="nav-link" id="RouterNavLink" style={None} to="/contact">anywords</Link>
you can try this in order to avoid the error
<NavItem as="li"> <Link>.....
I had same problem. It is because we can not use link, or a tag inside another like...
<a><a></a></a>
I wanted to apply className to my a tag in navigation bar. so i applied className to a tag in component and import that component in navigation bar component
<a className="nav-link" onClick={() => loginWithRedirect()}>
Login
</a>
This is how i use this link in navigation template,without any classname
<LoginButton />

React-Bootstrap - How to keep Navbar.Toggle button visible at all times?

I'm using React-Bootstrap to make a navigation menu. The toggle button once expanded contains my nav items to go to different parts of my app. So far I know it is supposed to be responsive to small-screened devices as the nav items disappear inside the toggle button as soon as the display width is smaller than 768px and appear inside the navbar if the screen is any wider.
What I want is to keep the toggle button, its behavior and its nav items (from the Navbar.Collapse) inside at all times. I've searched the documentation and other questions but haven't found any way to do this.
Here is my code :
import React from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { Glyphicon, Nav, Navbar, NavItem } from 'react-bootstrap';
import { actionCreators } from '../store/ExpeditionStore';
import './NavMenu.css';
const translations = require('../Translations');
class NavMenu extends React.Component {
render() {
return (
<Navbar inverse fixedTop fluid collapseOnSelect>
<Navbar.Header>
<Navbar.Toggle />
<Navbar.Brand>
{this.props.title}
</Navbar.Brand>
</Navbar.Header>
<Navbar.Collapse>
<Nav>
<NavItem>
<Glyphicon glyph='plane' />{translations.getCaption('shipment')}
</NavItem>
</Nav>
<Nav>
<NavItem onClick={() => this.props.switchLanguage(translations)}>
EN/FR
</NavItem>
</Nav>
</Navbar.Collapse>
</Navbar>
);
}
}
export default connect(
state => state.expeditionStore,
dispatch => bindActionCreators(actionCreators, dispatch)
)(NavMenu);
How to keep my toggle button and the Navbar.Collapse nav items inside it even if the device is wider than 768px?
Add expand attribute with value of "xl" or "xxl" to main Navbar tag. eg: expand="xxl"
Instead of using React-bootstrap approach, I suggest using normal bootstrap to achieve this result.
Put Bootstrap CDN link in your index.html file. Then this normal JSX code works for me:
<nav className="navbar narbar-expand-xl"> </nav>
Because the Bootstrap class narbar-expand-xl indicates that when screen equal or lower than the desktop size, the navbar will will collapse.

Categories

Resources