React Router link - reactjs

I'm using React Router with React-Bootstrap. This is the navigation component I have:
import React, { Component } from "react";
import { Link } from "react-router-dom";
import Navbar from "react-bootstrap/Navbar";
import { Nav } from "react-bootstrap";
import logo from "../assets/images/nav-logo.png";
import "bootstrap/dist/css/bootstrap.min.css";
import "../css/navigation.css";
class Navigation extends Component {
state = {
bg: "transparent",
variant: "dark",
className: "brand-visibility",
shadow: "",
};
listenScrollEvent = (e) => {
if (window.scrollY > 200 || window.innerWidth <= 767) {
this.setState({
bg: "white",
variant: "light",
className: "",
shadow: "nav-shadow",
});
} else {
this.setState({
bg: "transparent",
variant: "dark",
className: "brand-visibility",
shadow: "",
});
}
};
componentDidMount() {
window.addEventListener("scroll", this.listenScrollEvent);
window.addEventListener("resize", this.listenScrollEvent);
}
render() {
return (
<div>
<Navbar
id="white-bg"
collapseOnSelect
className={this.state.shadow}
fixed="top"
expand="md"
bg={this.state.bg}
variant={this.state.variant}
>
<Navbar.Brand className={this.state.className} as={Link} to="/">
<img
src={logo}
alt="logo"
style={{
height: "50px",
marginRight: "10px",
}}
/>
</Navbar.Brand>
<Navbar.Toggle aria-controls="responsive-navbar-nav" />
<Navbar.Collapse id="responsive-navbar-nav">
<Nav className="mr-auto"></Nav>
<Nav className="links">
<Nav.Link className="home-link" as={Link} to="/">
Home
</Nav.Link>
<Nav.Link className="why-us-link" as={Link} to="/why-us">
Why Us?
</Nav.Link>
<Nav.Link className="health-link" as={Link} to="/health&safety">
Health & Safety
</Nav.Link>
<Nav.Link
className="testimonials-link"
as={Link}
to="/testimonials" /*eventKey={2}*/
>
Testimonials
</Nav.Link>
<Nav.Link className="gallery-link" as={Link} to="/gallery">
Gallery
</Nav.Link>
<Nav.Link className="contact-link" as={Link} to="/contact-us">
Contact Us
</Nav.Link>
</Nav>
</Navbar.Collapse>
</Navbar>
</div>
);
}
}
export default Navigation;
I want to place this crayon underline image after the nav-link which is active. So it should look like this
I tried achieving this by using some css for different pages ( eg. by using home-link:after property). But all the underlines under nav-links are visible not matter which page is rendered. So how can I achieve this so that the crayon-underline is present only under the active nav-link?

Use NavLink instead of Link which adds the class active to the active link by default otherwise you can adjust the class with activeClassName or use activeStyle.

Related

Change nav bar text color in react

I want to update the text color of the content inside the bar, but for some reason it doesn't work.
What I've tried so far: Link a css stylesheet (it doesn't work for some reason)
inline style (it only works for the company name and the cart, not for the user's name)
Here is the code to my header:
import React from 'react'
import { Route } from 'react-router-dom'
import { useDispatch, useSelector } from 'react-redux'
import { LinkContainer } from 'react-router-bootstrap'
import { Navbar, Nav, Container, NavDropdown } from 'react-bootstrap'
import SearchBox from './SearchBox'
import { logout } from '../actions/userActions'
import '../index.css' //changes in index.css do not update in header.js
const Header = () => {
const dispatch = useDispatch()
const userLogin = useSelector((state) => state.userLogin)
const { userInfo } = userLogin
const logoutHandler = () => {
dispatch(logout())
}
return (
<header>
<Navbar style={{ backgroundColor: '#0a4275' }} variant="light" expand='lg' collapseOnSelect >
<Container >
<LinkContainer to='/'>
<Navbar.Brand><span style={{ color: 'white' }}> CFM Système</span></Navbar.Brand>
</LinkContainer>
<Navbar.Toggle aria-controls='basic-navbar-nav' />
<Navbar.Collapse id='basic-navbar-nav'>
<Route render={({ history }) => <SearchBox history={history} />} />
<Nav className='ml-auto'>
<LinkContainer to='/cart'>
<Nav.Link>
<span style={{ color: 'white' }}> <i className='fas fa-shopping-cart'></i> Panier</span>
</Nav.Link>
</LinkContainer>
{userInfo ? (
<NavDropdown title={userInfo.name} id='username'>
<LinkContainer to='/profile'>
<NavDropdown.Item>Profil</NavDropdown.Item>
</LinkContainer>
<NavDropdown.Item onClick={logoutHandler}>
Se déconnecter
</NavDropdown.Item>
</NavDropdown>
) : (
<LinkContainer to='/login'>
<Nav.Link>
<i className='fas fa-user'></i> Se connecter
</Nav.Link>
</LinkContainer>
)}
{userInfo && userInfo.isAdmin && (
<NavDropdown title='Admin' id='adminmenu'>
<LinkContainer to='/admin/userlist'>
<NavDropdown.Item>Utilisateurs</NavDropdown.Item>
</LinkContainer>
<LinkContainer to='/admin/productlist'>
<NavDropdown.Item>Produits</NavDropdown.Item>
</LinkContainer>
<LinkContainer to='/admin/orderlist'>
<NavDropdown.Item>Commandes</NavDropdown.Item>
</LinkContainer>
</NavDropdown>
)}
</Nav>
</Navbar.Collapse>
</Container>
</Navbar>
</header>
)
}
export default Header
I'm clearly missing something, but I'm out of solutions?

How to implement offcanvas on selected breakpoint on react router dom?

I did the navbar offcanvas across all breakpoints using the attribute expand={false} like the image below.
However i want the navbar items to be like the normal navigation on (min-width: 992px) OR expand="lg" like the image below. Im using reactrouter v6 and react-bootstrap.
Below is my code and also here is the working sandbox code https://codesandbox.io/.
import React, { useState } from "react";
import { Container, Navbar, Nav, Offcanvas } from "react-bootstrap";
import { NavLink, Outlet } from "react-router-dom";
const NavbarContent = () => {
const [isOpen, setOpen] = useState(false);
return (
<>
<Navbar
expanded={isOpen}
expand={false}
bg="light"
fixed="top"
className="bg-white text-the-primary bg-gradient shadow py-3"
>
<Container>
<Navbar.Brand href="/">
<span className="d-block fs-1">Offcanvas</span>{" "}
</Navbar.Brand>
<Navbar.Toggle
aria-controls="offcanvasNavbar"
onClick={() => setOpen(isOpen ? false : "expanded")}
/>
<Navbar.Offcanvas
id="offcanvasNavbar"
aria-labelledby="offcanvasNavbarLabel"
placement="end"
>
<Offcanvas.Header
closeButton
className="justify-content-end"
onClick={() => setOpen(false)}
></Offcanvas.Header>
<Offcanvas.Body>
<Nav className="justify-content-end flex-grow-1 pe-0">
<NavLink to="/" onClick={() => setOpen(false)}>
Home
</NavLink>
<NavLink to="/About" onClick={() => setOpen(false)}>
About
</NavLink>
</Nav>
</Offcanvas.Body>
</Navbar.Offcanvas>
</Container>
</Navbar>
<Outlet />
</>
);
};
export default NavbarContent;
I'm not sure if I missed something on useState and expand attribute of the navbar.
Set the expand break point to large using the command
<Navbar
expanded={isOpen}
expand='lg'
...
/>
Works for me

I want to Highlight the selected tab in Navbar on React BootStrap

I want to simply highlight the tab selected from the NavBar. I had used the Navbar Component of React-bootstrap and used the state to change the bgColor and textColor of the selected tab. But it is still NOT working? Any corrections?
import React,{useState} from 'react';
import { Navbar,Container, Nav } from "react-bootstrap"
import { LogOut } from "./LogOut"
const NavbarComponent = () => {
const [bgcolor, setBgcolor] = useState('black');
const [textcolor, setTextcolor] = useState('white');
function handleHighlightTab() {
setBgcolor('white');
setTextcolor('black');
}
return (
<>
<Navbar bg="dark" variant="dark" fixed='top' className='nav-pills'>
<Container>
<Navbar.Brand href="/">Verticals</Navbar.Brand>
<Nav className="me-auto">
<Nav.Link href="/grocery" onSelect={handleHighlightTab} style={{backgroundColor:{bgcolor},color:{textcolor} }} >Grocery</Nav.Link>
<Nav.Link href="/fashion" onSelect={handleHighlightTab} style={{backgroundColor:{bgcolor},color:{textcolor} }} >Fashion</Nav.Link>
<Nav.Link href="/footwear" onSelect={handleHighlightTab} style={{backgroundColor:{bgcolor},color:{textcolor} }}>Footwear</Nav.Link>
</Nav>
<LogOut />
</Container>
</Navbar>
</>
)
}
export default NavbarComponent;

How can I use state across multiple components?

I currently am storing user login in local storage and am rendering the appropriate nav bar depending. However, The page does not re-render upon sign-in or sign-out. I need to manually refresh the page to make it work. How can I use state in this scenario across several components?
import React, { useState } from "react";
import { Link } from "react-router-dom";
import { Navbar, Nav, Button } from "react-bootstrap";
import SignInModal from "././SignIn/SignInModal";
const NavBar = () => {
return localStorage.getItem("auth-token") ? <SignedIn /> : <SignedOut />;
};
const SignedIn = () => {
return (
<Navbar className="justify-content-around main-navbar">
<Nav.Item>
<Link className="link" to="/">
Signed Out
</Link>
</Nav.Item>
<Nav.Item>
<Link className="link" to="/mainsignedin">
Sign In
</Link>
</Nav.Item>
<Nav.Item>
<Link className="link" to="/searchpage">
Our Dogs
</Link>
</Nav.Item>
<Nav.Item>
<Link className="link" to="/mypets">
My Pets
</Link>
</Nav.Item>
<Nav.Item>
<Button type="submit" onClick={localStorage.clear()}>
Sign Out
</Button>
</Nav.Item>
</Navbar>
);
};
const SignedOut = () => {
return (
<Navbar>
<Nav.Item>
<SignInModal />
</Nav.Item>
</Navbar>
);
};
export default NavBar;
Here is code.
import SignInModal from "././SignIn/SignInModal";
import {useEffect, useState} from 'react';
const NavBar = () => {
const [isLogedIn,setIsloggedIn] =useState(false);
useEffect(()=>{
const auth_token = localStorage.getItem("auth-token") ;
setIsloggedIn(auth_token ? true:false);
},[])
const handleSignOut=()=>{
localStorage.clear()
setIsloggedIn(false);
}
return isLogedIn ? <SignedIn onSignOut={handleSignOut} /> : <SignedOut />;
};
const SignedIn = ({onSignOut}) => {
return (
<Navbar className="justify-content-around main-navbar">
<Nav.Item>
<Link className="link" to="/">
Signed Out
</Link>
</Nav.Item>
<Nav.Item>
<Link className="link" to="/mainsignedin">
Sign In
</Link>
</Nav.Item>
<Nav.Item>
<Link className="link" to="/searchpage">
Our Dogs
</Link>
</Nav.Item>
<Nav.Item>
<Link className="link" to="/mypets">
My Pets
</Link>
</Nav.Item>
<Nav.Item>
<Button type="submit" onClick={onSignOut}>
Sign Out
</Button>
</Nav.Item>
</Navbar>
);
};
const SignedOut = () => {
return (
<Navbar>
<Nav.Item>
<SignInModal />
</Nav.Item>
</Navbar>
);
};
export default NavBar;
You can use the useState hook to keep track of state in a React functional component.
You can use a Context to provide state to its children. Then, you can use the useContext hook within those children to access the state.
import React, { createContext, useContext } from 'react'
const MyContext = createContext({})
const MyContextProviderComponent = MyContext.Provider
const MyInnerComponent = () => {
const myValue = useContext(MyContext)
return <p>{myValue}</p>
}
const MyOuterComponent =() =>{
const [myValue, setMyValue] = useState('Hello world!')
return (
<MyContextProviderComponent value={myValue}>
<MyInnerComponent></MyInnerComponent>
</MyContextProviderComponent>
)
}

Gatsbyjs - collapsing navbar with reactstrap

I'm working on a site I've build with Gatsby.js, and reactstrap for the ui components. But I have an problem with the collapsed navbar on smaller screens.
I need to collapse the navigation after each click to make it work with gatsby-link, but the collapse is not collapsed after a new page is loaded.
So I added a closeNavbar method to all links via onClick, but for whatever reasons this does not work.
Here is my navigation component:
import React from "react";
import Link from "gatsby-link";
import {
Collapse,
Container,
Navbar,
NavbarToggler,
Nav,
NavItem
} from "reactstrap";
export default class Navigation extends React.Component {
constructor(props) {
super(props);
this.toggleNavbar = this.toggleNavbar.bind(this);
this.closeNavbar = this.closeNavbar.bind(this);
this.state = {
collapsed: true
};
}
toggleNavbar() {
this.setState({
collapsed: !this.state.collapsed
});
}
closeNavbar() {
if (this.state.collapsed == true) {
this.toggleNavbar();
}
}
render() {
return (
<header>
<Navbar className="navigation__navbar" light expand="md">
<Container>
<NavbarToggler onClick={this.toggleNavbar} className="mr-2" />
<Collapse isOpen={!this.state.collapsed} navbar>
<Nav className="mr-auto" navbar>
<NavItem>
<Link className="nav-link navigation__navlinks" to="/">
Home
</Link>
</NavItem>
<NavItem>
<Link
onClick={this.closeNavbar}
className="nav-link navigation__navlinks"
to="/leistungen/"
>
Leistungen
</Link>
</NavItem>
<NavItem>
<Link
onClick={this.closeNavbar}
className="nav-link navigation__navlinks"
to="/kuechen/"
>
Küchen
</Link>
</NavItem>
</Nav>
</Collapse>
</Container>
</Navbar>
</header>
);
}
}
I had an error in the closeNavbar method. I tried to toggle it, only when it was already collapsed. This is the correct code:
closeNavbar() {
if (this.state.collapsed !== true) {
this.toggleNavbar();
}
}

Resources