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;
Related
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?
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'm using React Context to store data into sessionstorage for the purposes of logging in and out. I'm saving three things: IDContext for saving the user's ID, UserNameContext for saving the user's username, and AdminContext to simply see if the logged in user is an admin or not. I want to display the logged in user's username on the navigation bar such as (Welcome, {user}) but instead it just displays as (Welcome, {}). I checked the sessionstorage via the developer tools, and it shows
username:""user""
So why exactly does it show up blank on the navigation bar, am I not grabbing the data correctly?
auth.js:
import { createContext, useContext } from "react";
export const UserNameContext = createContext();
export const IDContext = createContext();
export const AdminContext = createContext();
export function useUserName() {
return useContext(UserNameContext);
}
export function useID() {
return useContext(IDContext);
}
export function useAdmin() {
return useContext(AdminContext);
}
navbar.js:
import React from "react";
import { Navbar, Nav, Container } from "react-bootstrap";
import { Link } from "react-router-dom";
import { useID, useUserName, useAdmin } from "../context/auth";
function Navigation(props) {
const { IDTokens } = useID();
const { usernameTokens } = useUserName();
const { adminTokens } = useAdmin();
function adminNav() {
return (
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="me-auto">
<Link to="#">Placeholder</Link>
</Nav>
<Nav>
<Link to={`/${usernameTokens}`}>Welcome, {usernameTokens}</Link>
<Link to="/logout">Log Out</Link>
</Nav>
</Navbar.Collapse>
)
}
function loggedInNav() {
return (
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="me-auto">
<Link to="#">Placeholder</Link>
</Nav>
<Nav>
<Link to={`/${usernameTokens}`}>Welcome, {usernameTokens}</Link>
<Link to="/logout">Log Out</Link>
</Nav>
</Navbar.Collapse>
)
}
function guestNav() {
return(
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="me-auto">
<Link to="#">Placeholder</Link>
</Nav>
<Nav>
<Link to="/register">Register</Link>
<Link to="/login">Login</Link>
</Nav>
</Navbar.Collapse>
)
}
return (
<Navbar bg="primary" variant="dark" expand="md">
<Container>
<Link to="/">Flaskagram</Link>
<Navbar.Toggle aria-controls="basic-navbar-nav" />
{IDTokens && adminTokens ? (
adminNav()
) : IDTokens ? (
loggedInNav()
) : (
guestNav()
)}
</Container>
</Navbar>
)
}
export default Navigation;
You don't need three separate contexts for storing those 3 pieces of information. To make your user object accessible from anywhere in your app, add this line inside App.js (at the beginning of the App function):
const [user, setUser] = useState();
Make sure the useState hook is imported in App.js, as well as UserContext from wherever you will define your context (in your case, I believe it is auth.js).
Then, wrap all the jsx elements that are returned from App.js with the context provider like so:
export default function App() {
const [user, setUser] = useState();
// any other code you might have here
return (
<UserContext.Provider value={{ user, setUser }}>
// all your app's components here
</UserContext.Provider>
);
}
In auth.js, this is all you need:
import React from "react";
const UserContext = React.createContext();
export default UserContext;
Wherever you set the user object (most likely on your login page), just use the following line to access the setUser function (and don't forget to import UserContext):
const { setUser } = useContext(UserContext);
Now, in navbar.js:
import React, { useContext } from "react";
import { Navbar, Nav, Container } from "react-bootstrap";
import { Link } from "react-router-dom";
import UserContext from "../context/auth";
function Navigation() {
const {
user: { username, isAdmin },
} = useContext(UserContext);
function adminNav() {
return (
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="me-auto">
<Link to="#">Placeholder</Link>
</Nav>
<Nav>
<Link to={`/${username}`}>Welcome, {username}</Link>
<Link to="/logout">Log Out</Link>
</Nav>
</Navbar.Collapse>
);
}
function loggedInNav() {
return (
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="me-auto">
<Link to="#">Placeholder</Link>
</Nav>
<Nav>
<Link to={`/${username}`}>Welcome, {username}</Link>
<Link to="/logout">Log Out</Link>
</Nav>
</Navbar.Collapse>
);
}
function guestNav() {
return (
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="me-auto">
<Link to="#">Placeholder</Link>
</Nav>
<Nav>
<Link to="/register">Register</Link>
<Link to="/login">Login</Link>
</Nav>
</Navbar.Collapse>
);
}
return (
<Navbar bg="primary" variant="dark" expand="md">
<Container>
<Link to="/">Flaskagram</Link>
<Navbar.Toggle aria-controls="basic-navbar-nav" />
{username && isAdmin
? adminNav()
: username
? loggedInNav()
: guestNav()}
</Container>
</Navbar>
);
}
export default Navigation;
In order for this implentation to work, when you log the user in, the user object must have the properties of isAdmin and username set so that they can be accessed in the navbar. The isLoggedIn property is unnecessary because if the username property isn't null, it means that a user must be logged in.
Well, if you already have that item in your localstorage, you can just grab it using useEffect hook upon loading.
like this for example:
useEffect(() => {
const cachedUserName = JSON.parse(localStorage.getItem('username'));
if (cachedUserName ) {
setUserName(cachedUserName);
}
else {
...your logic
}
}, [setUserName]);
I want to create an SQL Editor. For that I need to display to which database I am currently connected to.
If I select some Database from the Dropdown Menu the Dropdown component will disappear completely.
Btw: I use the bootstrap library for Dropdown Menus
Here is what I got so far:
App.js
import Header from "./components/Header";
import Switch from "react-bootstrap/Switch";
import {Route, useParams} from "react-router";
import Navbar from "./components/Navbar";
import {useState} from "react";
import QueryPage from "./components/QueryPage";
import ChangeDB from "./components/essentials/ChangeDB";
function App() {
const [connections, setConnections] = useState([
{
id: 1,
dbname: "db1"
},
{
id: 2,
dbname: "db2"
},
{
id: 3,
dbname: "db3"
}]
);
const [db, setDB] = useState(1);
const onDBChange = ({id}) => {
setDB(() => id)
}
return (
<div className="App">
<Header database={db} connections={connections}/>
<Switch>
<Route exact path={["/", "/home","db/:id" ]}>
<QueryPage />
</Route>
<Route path="/db/:id"><ChangeDB callback={onDBChange} /></Route>
</Switch>
</div>
);
}
export default App;
Header.js
import {Button, Form, FormControl, Nav, Navbar, NavDropdown} from "react-bootstrap";
import "./Header.css";
import { Link } from 'react-router-dom';
function Header({ database , connections}) {
alert(database);
return (
<Navbar bg="light" expand="lg">
<Logo />
<Navbar.Brand href="#home">fnmSQL Client</Navbar.Brand>
<Navbar.Toggle aria-controls="basic-navbar-nav" />
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="mr-auto">
<Nav.Link href="#home">Home</Nav.Link>
<Nav.Link href="#link">Link</Nav.Link>
{connections.map(con => {
if(con.id === database) {
return (
<NavDropdown title={con.dbname} id="basic-nav-dropdown">
{connections.length !== 0 ?
connections.filter(id => (database !== id)).map(con => (
<NavDropdown.Item className={"bootstrap-overrides"} href={"#db/" + con.id}>{con.dbname}</NavDropdown.Item>
))
:
<NavDropdown.Item disabled="true">No Database Connections</NavDropdown.Item>
}
</NavDropdown>
)
}
})}
</Nav>
<Form inline>
<FormControl type="text" placeholder="Search" className="mr-sm-2" />
<Button variant="outline-success">Search</Button>
</Form>
</Navbar.Collapse>
</Navbar>
);
}
const Logo = () => {
return (
<Link to="./">
<img src={LogoWhite} alt={"ADVA Optical Networking SE"} className={"img"}/>
</Link>
)
}
export default Header;
I havent found another solution to read from HashRouter than putting it in some extra Component:
ChangeDB.js
function ChangeDB({callback}) {
let id = useParams();
callback(id);
return null;
}
export default ChangeDB;
Found a solution. It was because of the strict equality operator.
It seems that either database or con.id is parsed as a string instead of an integer.
I don't know why maybe somebody got an explanation...
Cheers guys
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>
)
}