React Bootstrap Nav.Link href/onSelect issues - reactjs

I am using React Bootstrap NavLink to main navigation. What I'm trying to do is:
Allow opening in new tab with correct route (no checking if it should be left needed)
If user wants to change current tab page - check if it should be left (eg some changes on current page may not be saved)
My current version looks like this:
{paths && paths.map(path =>
<NavLink href={path} onSelect={this.handleOnSelect}>
{path}
</NavLink>
}
And works quite alright, but the problem starts when my url looks like domain.com/a/b. Let's assume I click on c, navLink creates route domain.com/a/c instead of domain.com/c. I tried using href={`/${path}`} and routing worked fine but it was ignoring onSelect.
Does anyone have an idea how this could be solved? Is that even possible to accomplish?

Related

react-router-dom NavLink doesn't reflect isActive change without refreshing the page

I'm trying to use the NavLink's isActive prop to check whether the link's route is the current route to apply some visual styling.
Whenever I navigate to a page it works correctly as expected. However, if I tap a link while I'm inside a page, the changes aren't reflected to the components. The page and the address (which I presume is using history.pushState, which might be the culprit) updates instantly (without an actual HTTP page reload) but the old page still has the isActive property and the new one doesn't.
If I refresh the page which performs an actual "hard" reload, then the change is reflected.
Here is the relevant parts of the code (with actual paths anonymized) (styles is my imported module CSS with the relevant styles):
function NavigationBar(props:NavigationBarProps){
return <div className={styles['container']}>
<NavLink to={'/first'} className={props => `${styles['link']} ${props.isActive ? styles['selected'] : ''}`}>
first
</NavLink>
<NavLink to={'/second'} className={props => `${styles['link']} ${props.isActive ? styles['selected'] : ''}`}>
second
</NavLink>
<NavLink to={'/third'} className={props => `${styles['link']} ${props.isActive ? styles['selected'] : ''}`}>
third
</NavLink>
</div>
}
What am I doing wrong and how can I get it to work correctly (without implementing path changes manually and without disabling using history API, of course)?
I am on React 18.0.1, React-DOM 18.1.0, React-Router 6.3.0, React-Router-DOM 6.3.0 and connected-react-router 6.9.2.
UPDATE: I've also tried ditching connected-react-router (as it's suggested that it doesn't fully support react-router 6.x and seems like a dead library) and moving completely to https://github.com/salvoravida/redux-first-history yet still have the exact same problem.
UPDATE 2: This problem seems to be happening on Safari. It works correctly on Chrome and Firefox.
Maybe you want something like this example CodeSandbox

How to view the list of history paths in react-router?

Is it possible to view the list of paths in the history object? I can see that there is the length but I need to see the actual paths.
The reason for this is for debugging purpose. I have 2 views (SPA) that gets displayed via their corresponding URL. But my problem is when I go from the first page to the next page and then I wanted to go back to the first page, I need to click the browser back button 2 times before it goes back to the first page. That's the reason I wanted to see what are the paths in the history object so I can check what entries are being added because as far as I can see, the code I have to add a path to the history object is straightforward:
props.history.push("/classes/" + courseId);
That's just the code so I don't know why I need 2 clicks to go back to the previous page.
Not exactly sure how to see the history stack, but you might be unintentionally rendering the page twice, so the history.push is working as intended. You can log in componentDidMount to see if it does, and be careful when using useEffect because that can cause that as well. If you're using react router check how the route is added in your app.js (for ex do <Route path="/classes/:courseId" component={courseId}> instead of <Route path="/classes/:courseId" render={()=>courseId()}>.

reactjs routing to a specific section of a different page

from page 1 I am trying to route to a specific section of page 2.
I tried to use the hash value in the Link component but it did not work
<Link to={ {pathname: `/page2`, hash: `#sectionID`}} >
I even used this package react-router-hash-link with no success.
I always end up at the top of page 2.
any help
Check This link for full explanation;
Hash link scroll functionality for React Router, and here is example that will scroll to the component when you open it: baz#section-three, another one baz#section-two

How to override Back button when a drawer is showing in React 16 / Router V4

I have a structure like this, there's a route like:
<Route path="/sample-route" component={ComponentA}/>
Then ComponentA has:
<ComponentA>
<ComponentB/>
<ComponentC>
<MaterialUIDrawer/>
</ComponentC>
</ComponentA>
ComponentC is used in 5 different routes as a child. The MaterialUIDrawer is showing based on a flag in a redux reducer. The problem I'm trying to solve is when the drawer is open, clicking back hides it but also navigates back. I tried solving it like this:
window.onpopstate = (e) => {
if (this.props.isOpen) {
this.props.toggleDrawer(false);
this.props.history.replace(this.props.match.url);
}
};
This has 2 issues:
If this is the first page you land on, it doesn't actually do anything, the function doesn't trigger
If you are on a different site and navigate to the url that contains the drawer, hitting Back moves you to a different URL (different domain)
I also tried setting a <Route/> in ComponentC and then the drawer lives there, but I didn't manage to get it to work, maybe the path is wrong. It felt like this might be the right way though, if path is /path1, then drawer lives in /path1/drawer, or /path2/drawer, etc.
I'm trying to find a way for the Back button in a browser to close the drawer (so execute a function I define) and override the default functionality.
I think you should be using props here instead of paths, so something like /path1?drawer=1, but you will definitely need to use history/location so that the back button can actually go back, so you are on the right trail.
I'm not sure what you are using for a browser history manager, but I would recommend tying off of that instead of leaning on the window pop-state. Your history module should be the source of truth and feed redux, not the other-way around IMO.

React web navigation based on anchors

I'm trying to setup a single page react web application. My application only has one page with all the components places one after the other, so, the common react-router solution that lets you render only some part of the application doesn't work for me.
The intention is to have only one page (as large as it becomes) and the user can navigate between sections on it through a menu (or similar). Also, the site should recognize when someone types the URL like http://url.com/#section4, and scroll automatically to the requested section, marking the selected section on the menu as active.
Also, like a nice to have, it would be awesome if the URL can change depending on page scroll.
How can I achieve this?
I found this library that works in conjunction with the React Router's BrowserRouter, and allows to have a based anchor navigation, and also customize the scroll function were you can put offset or anything you wan to. Something like this:
<NavHashLink to="#anchor1" scroll={el => this.scroll(el)}>Anchor1</NavHashLink>
scroll (el) {
const offset = document.getElementById('element').offsetHeight
window.scrollTo({ top: el.offsetTop - offset, left: 0, behavior: 'smooth' })
}
You should either use HashRouter from react-router-dom package, or you can use a NavLink from the same package like this:
<NavLink>
to="/foo/#bar"
isActive={()=> window.location.pathname + window.location.hash === "/foo/#bar"}
</NavLink>

Resources