React Bootstrap: preserve current tab on page reload - javascript

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.

Related

Nav Menu Active Element and State Management Issue

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.

Next/router nothing happens when browser’s back button click

I don't understand why, when I click on browser’s back button my page doesn't reload.
I have a catalog component inside /pages/index.js which is my home page, a dynamic route to navigate to the products /pages/books/[name].js
This is the Link I use to go to the products pages :
<div className="container-cat">
{products.map((_product) => (
<Card id="lien" key={_product.id} alt="book" className="catalogue">
<Link href='/books/[name]' as={`/books/${_product.name}`}>
<a>
<Card.Body>
<Card.Img variant="top" src={getStrapiMedia(_product.grid_pic.url)} width="200px" />
<Card.Title>{_product.name}<br />{_product.author}<br />{_product.price} €</Card.Title>
</Card.Body>
</a>
</Link>
</Card>
))
}
</div>
I don't know what else to put here ...
I change my routes, putting the catalog component as the index.js of the /pages/books/
I can't really explain why, but it works

Menu does not collapse when you click on one of the menu items on Mobile Devices

Hi All i need some help :)
I working on a Gatsby, React portfolio where i have a problem with The Menu It does not collapse when you click on one of the menu items on Mobile Devices.
The menu is working fine on desktop.
The menu works fine on all devices until I installed the react-scroll package and set it up.
I have tried to search on Google for help and i found some simlare issues but i still dont know to fix the problem. :)
Hope you can help.
There is to Nav components i my project:
This my Project on SandBox:
NavBar.js
https://codesandbox.io/s/gatsby-starter-and-portfolio-jr9tn?file=/src/components/Navbar/Navbar.js
NavbarLinks:
https://codesandbox.io/s/gatsby-starter-and-portfolio-jr9tn?file=/src/components/Navbar/NavbarLinks.js
Here you have your CodeSandbox fixed: https://codesandbox.io/s/gatsby-starter-and-portfolio-forked-43thz?file=/src/components/Navbar/NavbarLinks.js
What was happening is that, since you've installed react-scroll, the state was never updated when an item was selected so, React's rehydration was never occurring and your menu was never closed. The code is a bit redundant however I've managed to get it to work. What I've added is a simple function passed via props that toggle the menu.
In your NavBar.js, instead of:
<Toggle
navbarOpen={navbarOpen}
onClick={() => setNavbarOpen(!navbarOpen)}
>
If added a function, since it's not a good practice to trigger effects directly bonded in the components. I've changed it to:
<Toggle navbarOpen={navbarOpen} onClick={toggleMenu}>
That toggleMenu function, is a simply function that does the same than your previous one:
const toggleMenu = () => setNavbarOpen(!navbarOpen)
Now, you have isolated that piece of functionality and you can reuse it, passing it to your child component (NavbarLinks):
{navbarOpen ? (
<Navbox>
<NavbarLinks toggleMenu={toggleMenu} />
</Navbox>
) : (
<Navbox open>
<NavbarLinks toggleMenu={toggleMenu} />
</Navbox>
)}
Note: this code is redundant, should be refactored to avoid that kind of unnecessary repetition. For example, something like this is much better:
<Navbox open={navbarOpen}>
<NavbarLinks toggleMenu={toggleMenu} />
</Navbox>
As you can see, you <NavbarLinks> have the functionality to toggle the menu in toggleMenu function so there you can trigger the function in every click (onClick):
const NavbarLinks = ({ toggleMenu })=> {
return (
<>
<NavItem
activeClass="active"
to="section1"
spy={true}
smooth={true}
duration={1000}
onClick={toggleMenu}
>
About
</NavItem>
<NavItem
activeClass="active"
to="section2"
spy={true}
smooth={true}
duration={1000}
onClick={toggleMenu}
>
Test
</NavItem>
<NavItem
activeClass="active"
to="section3"
spy={true}
smooth={true}
duration={1000}
onClick={toggleMenu)}
>
Gallery
</NavItem>
<NavItem to="/page-2">Contact</NavItem>
</>
)
}
Since you are destructuring props, you have the toggleMenu function available directly.

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 />

Unable to align ListItem text

I have this material-ui list:
<List dense>
{this.state.issues.map((item, i) => {
return <Link target="_blank" to={item.issue_url} key={i}>
<ListItem button>
<ListItemText primary={item.issue_state}/>
<ListItemSecondaryAction>
<IconButton>
<ArrowForward/>
</IconButton>
</ListItemSecondaryAction>
</ListItem>
</Link>
})
}
</List>
issue_state is obtained from MongoDB. Can I add another column to my list showing another field from the database? I tried:
<ListItemText primary={item.issue_state}/>
<ListItemText primary={item.issue_title}/>
This displays what I want but the issue_title test is centered. I'd like it left aligned. Can this be done?
ListItemText component renders with the following CSS style that allows it to be flexible to grow and shrink according as the width and height of its content.
flex: 1 1 auto;
Its ancestor ListItem component renders as an inline-flex.
AFAICT, the results you're looking to achieve can't be done without overriding these styles. Not to worry, there are other ways to go that uses available APIs exposed in the component.
Never mind that the name for the component seems to be misleading that its usage is specific for rendering text in the list item.
A closer look in the ListItemText component API documentation shows that the primary property is of the node type.
That implies that the ListItemText can be used to render string, function, and React.Element in a manner similar to the snippet below.
<ListItemText primary={<div>Foo<br/>Bar<br/>Baz</div>} />
There is also the secondary property that renders the elements with textual emphasis.
<ListItemText primary="Foo" secondary={<div>Bar<br/>Baz</div>} />
If you need more control over the children of the ListItemText, the API allows for the flexibility to write it this way
<ListItemText>
<Typography variant="subheading">Foo</Typography>
<Typography variant="body1" color="textSecondary">Bar</Typography>
<Typography variant="body1" color="textSecondary">Baz</Typography>
</ListItemText>

Categories

Resources