React underline react-bootstrap NavItem when scrolling down - javascript

I am trying to make a webpage where I have a react-bootstrap navbar with a few Nav items. I want to scroll through the page so that when I go to a new section, that particular NavItem is underlined or when I click on that NavItem, it automatically scrolls me through to that item.
I tried looking online and found react-scroll but do not know how to link it to my react-bootstrap code.
This is my Navbar Component
export const NavbarComponent = () => {
return (
<>
<Navbar collapseOnSelect className="style-navbar">
<Container>
<Navbar.Brand className="style-navbrand" href="/">
<div class="inl">LOGO</div>
<div className="style-subheading"Subheading</div>
</Navbar.Brand>
<Nav className="style-nav">
<Nav.Item className="style-navitem">
<Nav.Link className="style-navlink" href="/home">ABOUT</Nav.Link>
</Nav.Item>
<Nav.Item className="style-navitem">
<Nav.Link className="style-navlink" href="/members">MEMBERS</Nav.Link>
</Nav.Item>
<Nav.Item className="style-navitem">
<Nav.Link className="style-navlink" href="/pricing">Pricing</Nav.Link>
</Nav.Item>
</Nav>
<Nav>
<Nav.Link id="style-navlink" href="/contact">CONTACT</Nav.Link>
</Nav>
</Container>
</Navbar>
</>
This is my App.js
return (
<div className="style-background">
<div className = "style-backg-sheet">
<NavbarComponent/>
<AboutComponent/>
<MemberComponent/>
<PricingComponent/>
</div>
</div>
);
}
AboutComponent
import React from 'react'
import {Container} from 'react-bootstrap';
const About = () => {
return (
<div>
<Container>
<h1>About</h1>
<p>Some text</p>
</Container>
</div>
)
}
export default About
I basically wanted to have different sections as above on one page where if I click on a particular navbar item, it underlines that item and scrolls me down to it (if I click on Pricing, it scrolls me down to the pricing section which has a bit of text and pictures).

If all you want, at-a-minimum, is for the links to navigate to a specific section and underline the active menu item then I suggest the following:
Assign an id attribute to each "section" you care to link to.
const About = () => {
return (
<div className="section" id="about"> // <-- add id for each section
<Container>
<h1>About</h1>
<p>Some text</p>
</Container>
</div>
);
};
Use a hashlink in the nav items
<Nav.Link className="style-navlink" href="#about">
About
</Nav.Link>
Add the CSS to style the active menu item link
a.style-navlink.active {
color: #000;
font-weight: bold;
text-decoration: underline;
}
This will scroll the sections into view so long as everything is rendered inline as a single continuous document. What I see when trying to make the navbar "sticky" or "fixed" to the top so it doesn't scroll with the content, the rest of the content needs to be placed in a scrollable container and the default "scrolling-to" behavior breaks. You can fix this with third-party libraries. In this next section I chose react-router-hash-link to create hashlinks that have control over how content is scrolled to.
import { NavHashLink } from "react-router-hash-link";
...
<Nav.Link
activeClassName="active-link" // <-- define active classname
as={NavHashLink} // <-- render NavHashLink component
className="style-navlink"
smooth // <-- smooth scrolling
to="#about"
>
About
</Nav.Link>
...
.active-link {
color: #000;
font-weight: bold;
text-decoration: underline;
}

Related

Nav Link not rerendering page when clicked. Force update freezes page

I have a nav bar for a website I'm building. The links in the nav bar to a section (#id) in the page but do not go to the section and only update the url. If I type in the url in the address bar, it works correctly but when using the link nothing happens.
It only works if I force the page to rerender, but after rerendering the page freezes and I get an error in the console: Uncaught TypeError: Cannot read properties of undefined (reading 'forceUpdate'). I added an onClick and also tried using setState to force re-render.
Index.js
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>
);
App.js
function App() {
return (
<div>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/home" element={<Home />} />
</Routes>
</div>
);
}
export default App;
Home.jsx
function Home() {
return (
<div>
<Container fluid>
<NavBar />
<HomeContent />
</Container>
<Pricing />
<Footer />
</div>
);
}
export default Home;
NavBar.jsx
function handleClick() {
this.setState({ state: this.state });
// this.forceUpdate();
}
function NavBar() {
return (
<>
<Navbar variant="dark" expand="lg">
<Container>
<Navbar.Brand onClick={handleClick} as={Link} to="/home">
</Navbar.Brand>
<Navbar.Toggle aria-controls="basic-navbar-nav" />
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="justify-content-end flex-grow-1 pe-3">
<Nav.Link onClick={handleClick} as={Link} to="/home">
Home
</Nav.Link>
<Nav.Link onClick={handleClick} as={Link} to="/home#pricing">
Pricing
</Nav.Link>
</Nav>
</Navbar.Collapse>
</Container>
</Navbar>
</>
);
}
export default NavBar;
Pricing.jsx
function Pricing() {
return (
<section id="pricing">
<h2 className="section-heading">This is the pricing section</h2>
</section>
);
}
export default Pricing;
I also tried using withRouter on the NavBar component
I read that if I have to resort to forcing the page to render then I may be doing something wrong but I'm new to React and I've been searching for the past couple of days on better ways to do this but still couldn't find a better way to do it.
this.setState and this.forceUpdate are older React class-based-only component methods. They won't work in React function components.
react-router-dom alone doesn't deal/handle with hash links, i.e. navigating to a specific route path and then scrolling to a specific hash anchor. Currently the react-router-hash-link still works with react-router-dom#6. Import the HashLink from react-router-hash-link and use instead of the Link component from RRD.
Example:
import React from "react";
import { Nav, Navbar } from "react-bootstrap";
import { Link } from "react-router-dom";
import { HashLink } from "react-router-hash-link"; // <-- import hash link
function NavBar() {
return (
<Navbar bg="dark" variant="dark" expand="lg">
<Navbar.Brand as={Link} to="/home"></Navbar.Brand>
<Navbar.Toggle aria-controls="basic-navbar-nav" />
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="justify-content-end flex-grow-1 pe-3">
<Nav.Link as={Link} to="/home">
Home
</Nav.Link>
<Nav.Link as={HashLink} to="/home#pricing"> // <-- hash link
Pricing
</Nav.Link>
<Nav.Link as={HashLink} to="/home#about"> // <-- hash link
About
</Nav.Link>
<Nav.Link as={HashLink} to="/home#contact"> // <-- hash link
Contact
</Nav.Link>
</Nav>
</Navbar.Collapse>
</Navbar>
);
}
export default NavBar;
The best way to solve your problem to create React router structure in your web app. I suggest you to go through React router beginners page.
Also, in your case I suggest to create React router structure such as this structure:
You will have the main index.js file:
const router = createBrowserRouter([
{
path: "/",
element: <Layout />,
children: [
{
path: "mainpage/",
element: <MainPage />,
},
],
},
]);
You will not have app.js file. You will just have a layout.jsx file:
import { Outlet } from 'react-router-dom';
import Nav from "./components/Nav";
const Layout = () => {
return (<>
<Nav />
<Outlet />
</>)
}
And you should just add paths and more children to index js. Just create some components and add them to children array as a main page one.
And in your nav component you must have links to your pages like in the following nav component example:
import React from 'react';
import { Link } from "react-router-dom";
function Nav(props) {
return (
<header className="header">
<div className="header-container">
<nav className="header-nav">
<ul className="nav-list">
<li>
<Link to={`mainpage/`}>Home</Link>
</li>
<li>
<Link to={`News/`}>News</Link>
</li>
<li>
<Link to={`About/`}>About</Link>
</li>
<li>
<Link to={`Contacts`}>Contacts</Link>
</li>
</ul>
</nav>
</div>
</header>
);
}
export default Nav;
I hope you will solve your issue.

Cannot get navbar to function on collapse using react-bootstrap

I'm using react-bootstrap to create a responsive navbar and for some reason it will not work. I've tried using react-router-dom to handle page change and creating a function withing the navbar to handle page change to see if that was the issue. The hamburger icon is not even rendering just a gray blank square.
This is my current code
And here is what it renders
What else can I try?
import Container from 'react-bootstrap/Container';
import Nav from 'react-bootstrap/Nav';
import Navbar from 'react-bootstrap/Navbar'
import '../css/Navbar.css'
export default function NavbarRender({ currentPage, handlePageChange }){
return(
<Navbar collapseOnSelect expand='sm' id='total-nav'>
<Container>
<Navbar.Toggle aria-controls="responsive-navbar-nav"/>
<Navbar.Collapse id="responsive-navbar-nav">
<Nav className="me-auto">
<Nav.Link href="#about" onClick={() => handlePageChange('About')}
className={currentPage === 'About' ? 'nav-link active' : 'nav-link'} id="navbar">
About
</Nav.Link>
<Nav.Link href="#portfolio" onClick={() => handlePageChange('Portfolio')}
className={currentPage === 'Portfolio' ? 'nav-link active' : 'nav-link'} id="navbar">
Portfolio
</Nav.Link>
<Nav.Link href="#resume" onClick={() => handlePageChange('Resume')}
className={currentPage === 'Resume' ? 'nav-link active' : 'nav-link'} id="navbar">
Resume
</Nav.Link>
</Nav>
</Navbar.Collapse>
</Container>
</Navbar>
);
}
I have that problem when forget to import react-boostrap CSS
{/* The following line can be included in your src/index.js or App.js file*/}
import 'bootstrap/dist/css/bootstrap.min.css';

React Bootstrap Navbar contents not filling the width of the screen

Total web dev noob here. Just integrated Bootstrap for the first time, and I'm using a set of Navbars gotten off this link : https://react-bootstrap.github.io/components/navbar/
I've noticed that, while the style is correct and everything looks normal, the text content of the Navbar is not filling the entire width of the Bar. picture shown below
[![enter image description here][1]][1]
Navbar File code extract
class Navsucks extends Component {
// componentDidMount() {
// }
render() {
return (
<Navbar collapseOnSelect expand="lg" bg="dark" variant="dark" >
<Container>
<Navbar.Brand href="#home">React-Bootstrap</Navbar.Brand>
<Navbar.Toggle aria-controls="responsive-navbar-nav" />
<Navbar.Collapse id="responsive-navbar-nav">
<Nav className="me-auto">
<Nav.Link href="#features">Features</Nav.Link>
<Nav.Link href="#pricing">Pricing</Nav.Link>
<NavDropdown title="Dropdown" id="collasible-nav-dropdown">
<NavDropdown.Item href="#action/3.1">Action</NavDropdown.Item>
<NavDropdown.Item href="#action/3.2">Another action</NavDropdown.Item>
<NavDropdown.Item href="#action/3.3">Something</NavDropdown.Item>
<NavDropdown.Divider />
<NavDropdown.Item href="#action/3.4">Separated link</NavDropdown.Item>
</NavDropdown>
</Nav>
<Nav>
<Nav.Link href="#deets">More deets</Nav.Link>
<Nav.Link eventKey={2} href="#memes">
Dank memes
</Nav.Link>
</Nav>
</Navbar.Collapse>
</Container>
</Navbar>
);
}
}
App.js code extract
class App extends Component {
state = { posty: []}
componentDidMount() {
}
render() {
return (
<div className="App">
<Navsucks> </Navsucks>
<header className="App-header">
<Texts> asdasd </Texts>
</header>
</div>
);
}
}
export default App;
I really just want the left and right halves of the text to be hugging the screen edges. Is this possible? Any help is much appreciated!
Thanks!

(React) Sliding/Sticky navbar hidden behind images?

My sliding navbar gets sucked in at the top and when i scroll down it is behind the images.
I want it to be in front of the images like what this website does https://www.w3schools.com/howto/howto_js_navbar_sticky.asp (yes i tried following their code exactly but then i get TypeError: Navbar is null) (So i was trying to code a different version based off of theirs)
my code
Header.js
import React, { Fragment } from 'react'
import { Navbar, Nav } from 'react-bootstrap'
import './Header.scss'
const alwaysOptions = (
<Fragment>
<Nav.Link href="#/" className="btn btn-light">Home</Nav.Link>
<Nav.Link href="#/Anime-list" className="btn btn-warning">Anime List</Nav.Link>
<Nav.Link href="https://notARealSite.com" target='_blank' rel="noopener noreferrer" className="btn btn-danger">Cartoons</Nav.Link>
</Fragment>
)
const Header = ({ user }) => (
<Navbar bg="dark" expand="md" id="navbar">
<Navbar.Brand href="#">
<h3 className="navbarTitle">Anime Stream</h3>
</Navbar.Brand>
<Navbar.Toggle aria-controls="basic-navbar-nav" />
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="ml-auto">
{ alwaysOptions }
</Nav>
</Navbar.Collapse>
</Navbar>
)
window.onscroll = function () { scrollFunction() }
const scrollFunction = () => {
if (document.body.scrollTop > 20 || document.documentElement.scrollTop > 20) {
document.getElementById('navbar').style.top = '0'
} else {
document.getElementById('navbar').style.top = '-50px'
}
}
export default Header
Header.scss
#import "~bootstrap/scss/bootstrap";
#navbar {
position: fixed;
top: -50px;
width: 100%;
transition: top 0.3s;
}
output: https://prnt.sc/10vcl0j (the navbar is sucked in at the top of the page)
2nd output (after scrolling down): https://prnt.sc/10vcm7e (the navbar is behind the images)
I suspect that if you look at the CSS attached to those images, you'll find that they have a z-index assigned. Try setting your navbar's z-index higher than theirs.
samuei

React js- bootstrap Value not showing on Tab change

I am making a React App. I am using react-bootstrap to make it.But while trying to show content on different nav items by using the Tab.Content and Tab.Pane , the value shows in the default nav correctly on page refresh but if I go to the other nav item , the content does not show up and the content of the default value also gets blank.If i again refresh the page the value on the default nav item shows up and then the same thing happen. Please help me.
Error lies in between line 22 to line 29.
import React, { useState } from 'react';
import { Tab, Nav } from 'react-bootstrap'
import Conversations from './Conversations'
import Contacts from './Contacts'
const Sidebar = (props) => {
const [activeKey, setActiveKey] = useState('conversations')
return (
<div style={{ width: '250px' }} className='d-flex flex-column' >
<Tab.Container activeKey={activeKey} onSelect={() => setActiveKey(null)} >
<Nav variant='tabs' className='justify-content-center mt-1' >
<Nav.Item>
<Nav.Link eventKey='conversations' >Conversations</Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link eventKey='contacts' >Contacts</Nav.Link>
</Nav.Item>
</Nav>
<Tab.Content >
<Tab.Pane eventKey='conversations' >
<Conversations />
</Tab.Pane>
<Tab.Pane eventKey='contacts' >
<Contacts />
</Tab.Pane>
</Tab.Content>
</Tab.Container>
</div>
)
}
Based on https://react-bootstrap.github.io/components/tabs/#tabs-controlled , I suspect that:
onSelect={() => setActiveKey(null)}
should be:
onSelect={(key) => setActiveKey(key)}
Edit: I've tried this change out locally now and it appears to work.

Categories