The Profile Picture is not visible on the Top Bar - reactjs

This a blog page using the Fullstack MERN Application. And it should show the uploaded Profile pic of the user when the particular user is Logged in on the Top bar. But in my case it is not showing up. Same thing is happening for the About me Image. But the difference is that the Image in the About me component is visible when the user is logging out and then logging in again.
The code for the Top Bar component is :
import { useContext } from "react";
import { Link } from "react-router-dom";
import { Context } from "../../context/Context";
import "./topbar.css";
export default function TopBar() {
const { user, dispatch } = useContext(Context);
const PF = "http://localhost:5000/images"
// console.log(PF+user.profilePic)
const handleLogout = () => {
dispatch({ type: "LOGOUT" });
};
return (
<div className="top">
<div className="topLeft">
<i className="topIcon fab fa-facebook-square"></i>
<i className="topIcon fab fa-twitter-square"></i>
<i className="topIcon fab fa-pinterest-square"></i>
<i className="topIcon fab fa-instagram-square"></i>
</div>
<div className="topCenter">
<ul className="topList">
<li className="topListItem">
<Link className="link" to="/">
HOME
</Link>
</li>
<li className="topListItem">
<Link className="link" to="/">
ABOUT
</Link>
</li>
<li className="topListItem">
<Link className="link" to="/">
CONTACT
</Link>
</li>
<li className="topListItem">
<Link className="link" to="/write">
WRITE
</Link>
</li>
<li className="topListItem" onClick={handleLogout}>
{user && "LOGOUT"}
</li>
</ul>
</div>
<div className="topRight">
{user ? (
<Link to="/settings">
<img className="topImg" src={PF + user.profilePic} alt="" />
</Link>
) : (
<ul className="topList">
<li className="topListItem">
<Link className="link" to="/login">
LOGIN
</Link>
</li>
<li className="topListItem">
<Link className="link" to="/register">
REGISTER
</Link>
</li>
</ul>
)}
<i className="topSearchIcon fas fa-search"></i>
</div>
</div>
);
}
COde For the Sidebar:
import axios from "axios";
import { useEffect, useState } from "react";
import { Link } from "react-router-dom";
import "./sidebar.css";
import { useContext } from "react";
import { Context } from "../../context/Context";
export default function Sidebar() {
const [cats, setCats] = useState([]);
const { user } = useContext(Context);
const PF = "http://localhost:5000/images/";
useEffect(() => {
const getCats = async () => {
const res = await axios.get("/categories");
setCats(res.data);
};
getCats();
}, []);
return (
<div className="sidebar">
<div className="sidebarItem">
<span className="sidebarTitle">ABOUT ME</span>
{user && <img
src={PF + user.profilePic}
alt=""
/>}
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptate qui
necessitatibus nostrum illum reprehenderit.
</p>
</div>
<div className="sidebarItem">
<span className="sidebarTitle">CATEGORIES</span>
<ul className="sidebarList">
{cats.map((c) => (
<Link to={`/?cat=${c.name}`} className="link">
<li className="sidebarListItem">{c.name}</li>
</Link>
))}
</ul>
</div>
<div className="sidebarItem">
<span className="sidebarTitle">FOLLOW US</span>
<div className="sidebarSocial">
<i className="sidebarIcon fab fa-facebook-square"></i>
<i className="sidebarIcon fab fa-twitter-square"></i>
<i className="sidebarIcon fab fa-pinterest-square"></i>
<i className="sidebarIcon fab fa-instagram-square"></i>
</div>
</div>
</div>
);
}
The Image of the Top Bar
Also when the user is uploading the image a random no. is added in front of the file in the Data base which
I have manually remove to load the image to the server. As it is not able to read it like:
The random numbers in frond of the name of the file
I tried some Stack over flow answer like:TypeError: Cannot read property 'image' of null
This helped me with the Side bar problem but not fully.

Related

How to display username on navbar after login in react redux

There is a nav link on my navbar named Login (I have used bootstrap navbar). After successful login I want to replace Login with a username using react-redux (not redux-toolkit).
Kindly help me in writing reducer and action code. As I am a beginner in redux and I don't know how to code in reducer and action file it is very confusing for me.
Navbar component (Navbar.js)
import React from 'react';
import { Link } from 'react-router-dom';
import { useSelector } from 'react-redux';
const Navbar = () => {
const {username} = useSelector((state) => state.user);
return (
<div>
<nav className="navbar navbar-expand-lg">
<div className="container-fluid">
<Link className="navbar-brand" to="/hommepage">Ebuy</Link>
<button className="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria- expanded="false" aria-label="Toggle navigation">
<span className="navbar-toggler-icon">
<i className="fas fa-bars" style={{color: 'white', fontSize: '28px'}}></i>
</span>
</button>
<div className="collapse navbar-collapse" id="navbarSupportedContent">
<ul className="navbar-nav me-auto mb-2 mb-lg-0">
<li className="nav-item">
<Link className="nav-link" aria-current="page" to="/homepage">Home</Link>
</li>
<li className="nav-item dropdown">
<Link className="nav-link dropdown-toggle" to="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
Select Category
</Link>
<ul className="dropdown-menu" aria-labelledby="navbarDropdown">
<li><Link className="dropdown-item" to="/skincare">Skincare Products</Link></li>
<li><Link className="dropdown-item" to="/stationary">Stationary Products</Link></li>
<li><Link className="dropdown-item" to="#">Clothing</Link></li>
</ul>
</li>
</ul>
<div className="d-flex">
<ul className="navbar-nav me-auto mb-2 mb-lg-0">
<li className='nav-item'>
<Link className="nav-link" to="/">Login</Link>
</li>
</ul>
</div>
</div>
</div>
</nav>
</div>
);
};
export default Navbar;
reducer
const initialState = {
username: null,
}
export const userReducer(state = initialState, action) {
switch (action.type) {
case "CHANGE_USERNAME":
return {
...state,
username: action.payload,
}
default:
return state
}
}
action
export const changeUserName = (name) => {
return {
type: "CHANGE_USERNAME",
payload: name
}
}
after login call this
const dispatch = useDispatch()
const login = () => {
... login logic here
dispatch(changeUserName("user-1"))
}
in navbar
const { username } = useSelector(state=> state.user)
In your Navbar Component you should get username from redux, please try this :
const {username} = useSelector(state=> state.yourReducerName)
after this, in your jsx : you should write a condition like this :
{username ? (<div>{username}</div>): ()<span>Login</span>}
EDIT :
Please refer to this sandbox example and take a look on the reducer and actions files, also on the navbar components.
Let us know if the post helped you :)

NextJS and bootstrap mobile nav

I'm using bootstrap with NextJS for my navbar but have one issue because of the dynamic page changes with React and Next on mobile view the menu stays open after clicking a link and loading new page.
Tried a few ways to try and make it close on page changes but been unsuccessful. What would be best way to achieve this?
import { useEffect } from 'react'
import Link from 'next/link'
import Image from 'next/image'
import { ArrowDownCircle } from 'react-bootstrap-icons'
import logo from '../public/images/logo.gif'
import styles from '../styles/Navbar.module.scss'
const Navbar = () => {
useEffect(() => {
import('bootstrap/js/dist/collapse')
import('bootstrap/js/dist/dropdown')
}, []);
return (
<nav id="navbar" className="navbar navbar-expand-md navbar-light container">
<div>
<Link href="/" prefetch={false}><a className="navbar-brand">
<Image
src={logo}
alt="Logo"
layout="intrinsic"
width={200}
height={50}
priority={true}
/>
</a></Link>
</div>
<button className="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span className="navbar-toggler-icon"></span>
</button>
<div className="collapse navbar-collapse" id="navbarNav">
<ul className={`${styles.navLink} navbar-nav ms-auto`}>
<li className="nav-item">
<Link href="/" prefetch={false}><a className={`${styles.link} nav-link`} aria-current="page">Home</a></Link>
</li>
<li className="nav-item">
<Link href="/about" prefetch={false}><a className={`${styles.link} nav-link`}>About</a></Link>
</li>
<li className="nav-item dropdown">
<a className={`${styles.link} nav-link`} id="navbarDropdownMenuLink" role="button" data-bs-toggle="dropdown" aria-expanded="false">Services <ArrowDownCircle className="ms-1" /></a>
<ul className="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
<li><Link href="/web-design"><a className="dropdown-item">Web Design</a></Link></li>
<li><Link href="/web-development"><a className="dropdown-item">Web Development</a></Link></li>
<li><Link href="/ecommerce"><a className="dropdown-item">eCommerce</a></Link></li>
</ul>
</li>
<li className="nav-item">
<Link href="/faq" prefetch={false}><a className={`${styles.link} nav-link`}>FAQ</a></Link>
</li>
<li className="nav-item">
<Link href="/contact" prefetch={false}><a className={`${styles.link} nav-link`}>Contact</a></Link>
</li>
</ul>
</div>
<style jsx>{`
a {
background: none;
}
a:hover {
background: none;
}
`}</style>
</nav>
);
}
export default Navbar;
If anyone still looking for solution in 2022 or later, follow these steps:
Note: This solution was tested on NextJs (Typescript) + Bootstrap v.5.2
Add an id to the button with class navbar-toggler i.e. <button id="navbar-toggler" className="navbar-toggler" ...
In your component class, say Header.tsx
Import useRouter and useEffect:
import { useRouter } from 'next/router'
import { useEffect } from 'react'
and within your component function:
const Header = () => {
const router = useRouter()
useEffect(() => {
const handleRouteChange = (url: String) => {
if (typeof window !== undefined && window.screen.width <= 991.98) { // change the width value according to your navbar breakpoint
const navbar = document.getElementById("navbar-toggler");
if (navbar !== null && !navbar.classList.contains('collapsed')) navbar.click()
}
}
router.events.on('routeChangeComplete', handleRouteChange)
}, [router.events])
return (<> ... other codes </>)
}
export default Header

react-router-dom Link does not navigate to the start of target pages

I'm using react-router-dom Link on Home page to navigate to some routes. It works correctly when I'm at the top of Home Page. But when I scroll down the Home and click the Link items in navbar, although it navigates to the specified route, the target page is not displayed from the top. It starts somewhere in the middle of the page.
Here's my navbar:
import React, { Fragment, useState } from "react";
import { Link } from "react-router-dom";
import Fade from "react-reveal/Fade";
import EduLogo from "./resource/edu.png";
import Logo from "./resource/logo.png";
const Navbar = () => {
const [nav, setNav] = useState(false);
const adjustNav = () => {
if (window.scrollY >= 1) {
setNav(true);
document.getElementById("main-nav").style.height = "100px";
document.getElementById("nav-logo").style.height = "30px";
document.getElementById("nav-logo").style.width = "275px";
document.getElementById("nav-edu").style.height = "65px";
document.getElementById("nav-edu").style.width = "200px";
} else {
setNav(false);
document.getElementById("main-nav").style.height = "120px";
document.getElementById("nav-logo").style.height = "37px";
document.getElementById("nav-logo").style.width = "360px";
document.getElementById("nav-edu").style.height = "80px";
document.getElementById("nav-edu").style.width = "238px";
}
};
window.addEventListener("scroll", adjustNav);
return (
<Fragment>
<nav id="main-nav" className={nav ? "main-nav active" : "main-nav"}>
<Fade left>
<div id="main-nav-logo">
<a href="#!" target="_blank">
<img src={EduLogo} alt="" id="nav-edu" />
</a>
<img
src={Logo}
alt=""
id="nav-logo"
/>
</div>
</Fade>
<div className="nav-container">
<Fade bottom cascade>
<ul>
<li id="nav-item">
<Link to="/" className="nav-item">
Home
</Link>
</li>
<li id="nav-item">
<Link to="/members" className="nav-item">
Who We Are?
</Link>
</li>
<li id="nav-item">
<Link to="/research" className="nav-item">
What We Do?
</Link>
</li>
<li id="nav-item">
<Link to="/latest" className="nav-item">
News & Events
</Link>
</li>
</ul>
</Fade>
</div>
</nav>
</Fragment>
);
};
export default Navbar;
Any suggestion?
Thanks
I normally use something like this to make sure that my page is shown from the top whenever it is visited.
React.useLayoutEffect(() => {
window.scrollTo(0, 0);
}, [])
I use the useLayoutEffect hook to apply the window scroll before the browser starts painting.
You can read more about it here

How Can I set State in stateless Function, in a nested Function?

I know that I can't change the state in a stateless function when the function is nested, though I am only this far away to set the state in order for the page work as I would want. I want to keep this as a functional component. The issue is below I want to set the language under this function, or any other way works I know how to do this with Class component, though unless there will be 10 votes to do that would prefer to stay with functional.
function changeTounge(e) {
console.log("Write something!!");
console.log(e.currentTarget.dataset.id);
console.log(e.currentTarget.dataset.value);
//setLanguage({ iso2: "lv", speak: "Latviešu" });
}
the full code is:
import React, { useState } from "react";
import { Link } from "react-router-dom";
export function PrimaryNav() {
const [language, setLanguage] = useState({ iso2: "us", speak: "English" });
return (
<div className="primary-nav">
<ul className="navigation">
<li className="active">
<Link to="/">Home</Link>
</li>
<li className="has-child">
Opportunities
<div className="wrapper">
<div id="nav-homepages" className="nav-wrapper">
<ul>
{OpsOption("RealEstate", "Real Estate")}
{OpsOption("Vehicles", "Vehicles")}
{OpsOption("JobSearch", "Job Search")}
{OpsOption("PersonalCompany", "Personal Company")}
{OpsOption("Inves`enter code here`tInIdea", "Invest In Idea")}
</ul>
</div>
</div>
</li>
<li>
<Link to="/contact">Help & Support</Link>
</li>
<li className="has-child language">
{ActiveLanguage(language.iso2, language.speak)}
<div className="wrapper">
<div id="nav-languages" className="nav-wrapper">
<ul>
{LanguageOption("English", "us")}
{LanguageOption("British", "gb")}
{LanguageOption("Latviešu", "lv")}
{LanguageOption("Estonia", "ee")}
{LanguageOption("Lithuania", "lt")}
{LanguageOption("Russian", "ru")}
{LanguageOption("Deutch", "de")}
{LanguageOption("French", "fr")}
</ul>
</div>
</div>
</li>
</ul>
</div>
);
}
function LanguageOption(label, classLabel) {
return (
<li
onClick={changeTounge.bind(this)}
data-id={label}
data-value={classLabel}
>
<Link to="#nav-locations">
<span className={"flag-icon flag-icon-" + classLabel}></span>
{" "}
{label}
</Link>
</li>
);
}
function changeTounge(e) {
console.log("Write something!!");
console.log(e.currentTarget.dataset.id);
console.log(e.currentTarget.dataset.value);
//setLanguage({ iso2: "lv", speak: "Latviešu" });
}
function OpsOption(pageLink, label) {
return (
<li>
<Link to={"/" + pageLink}>{label}</Link>
</li>
);
}
function ActiveLanguage(iso2, activeLanguage) {
return (
<a href="#nav-languages">
<span className={"flag-icon flag-icon-" + iso2}></span> {activeLanguage}
</a>
);
}
export default PrimaryNav;
Try nesting the components inside of the main component, they'll be able to access and set its state. This is still a functional pattern here.
The other option would be to add a prop to your children components, and pass in the setLanguage function through that prop.
Also, you don't need the changeTounge.bind.this in functional react :D. In general, if you're using this at all in functional react... that's a red flag.
import React, { useState } from "react";
import { Link } from "react-router-dom";
const PrimaryNav = () => {
const [language, setLanguage] = useState({ iso2: "us", speak: "English" });
const changeTounge = (e) => {
console.log("Write something!!");
console.log(e.currentTarget.dataset.id);
console.log(e.currentTarget.dataset.value);
setLanguage({ iso2: "lv", speak: "Latviešu" });
}
const OpsOption = (pageLink, label) => {
return (
<li>
<Link to={"/" + pageLink}>{label}</Link>
</li>
);
}
const ActiveLanguage = (iso2, activeLanguage) => {
return (
<a href="#nav-languages">
<span className={"flag-icon flag-icon-" + iso2}></span> {activeLanguage}
</a>
);
}
const LanguageOption = (label, classLabel) => {
return (
<li
onClick={changeTounge}
data-id={label}
data-value={classLabel}
>
<Link to="#nav-locations">
<span className={"flag-icon flag-icon-" + classLabel}></span>
{" "}
{label}
</Link>
</li>
);
}
return (
<div className="primary-nav">
<ul className="navigation">
<li className="active">
<Link to="/">Home</Link>
</li>
<li className="has-child">
Opportunities
<div className="wrapper">
<div id="nav-homepages" className="nav-wrapper">
<ul>
{OpsOption("RealEstate", "Real Estate")}
{OpsOption("Vehicles", "Vehicles")}
{OpsOption("JobSearch", "Job Search")}
{OpsOption("PersonalCompany", "Personal Company")}
{OpsOption("Inves`enter code here`tInIdea", "Invest In Idea")}
</ul>
</div>
</div>
</li>
<li>
<Link to="/contact">Help & Support</Link>
</li>
<li className="has-child language">
{ActiveLanguage(language.iso2, language.speak)}
<div className="wrapper">
<div id="nav-languages" className="nav-wrapper">
<ul>
{LanguageOption("English", "us")}
{LanguageOption("British", "gb")}
{LanguageOption("Latviešu", "lv")}
{LanguageOption("Estonia", "ee")}
{LanguageOption("Lithuania", "lt")}
{LanguageOption("Russian", "ru")}
{LanguageOption("Deutch", "de")}
{LanguageOption("French", "fr")}
</ul>
</div>
</div>
</li>
</ul>
</div>
);
}
export default PrimaryNav;
There are probably tidier ways to do some of this, but this seems to work:
import React, { useState } from "react";
import { Link } from "react-router-dom";
export function PrimaryNav() {
const [language, setLanguage] = useState({ iso2: "us", speak: "English" });
return (
<div className="primary-nav">
<ul className="navigation">
<li className="active">
<Link to="/">Home</Link>
</li>
<li className="has-child">
Opportunities
<div className="wrapper">
<div id="nav-homepages" className="nav-wrapper">
<ul>
{OpsOption("RealEstate", "Real Estate")}
{OpsOption("Vehicles", "Vehicles")}
{OpsOption("JobSearch", "Job Search")}
{OpsOption("PersonalCompany", "Personal Company")}
{OpsOption("Inves`enter code here`tInIdea", "Invest In Idea")}
</ul>
</div>
</div>
</li>
<li>
<Link to="/contact">Help & Support</Link>
</li>
<li className="has-child language">
{ActiveLanguage(language.iso2, language.speak)}
<div className="wrapper">
<div id="nav-languages" className="nav-wrapper">
<ul>
{LanguageOption("English", "us", setLanguage)}
{LanguageOption("British", "gb", setLanguage)}
{LanguageOption("Latviešu", "lv", setLanguage)}
{LanguageOption("Estonia", "ee", setLanguage)}
{LanguageOption("Lithuania", "lt", setLanguage)}
{LanguageOption("Russian", "ru", setLanguage)}
{LanguageOption("Deutch", "de", setLanguage)}
{LanguageOption("French", "fr", setLanguage)}
</ul>
</div>
</div>
</li>
</ul>
</div>
);
}
function LanguageOption(label, classLabel, setLanguage) {
return (
<li
onClick={(event) => changeTounge(event, setLanguage, label, classLabel)}
data-id={label}
data-value={classLabel}
>
<Link to="#nav-locations">
<span className={"flag-icon flag-icon-" + classLabel}></span>
{" "}
{label}
</Link>
</li>
);
}
function changeTounge(e, setLanguage, label, classLabel) {
console.log("Write something!!");
console.log(e.currentTarget.dataset.id);
console.log(e.currentTarget.dataset.value);
setLanguage({ iso2: classLabel, speak: label });
}
function OpsOption(pageLink, label) {
return (
<li>
<Link to={"/" + pageLink}>{label}</Link>
</li>
);
}
function ActiveLanguage(iso2, activeLanguage) {
return (
<a href="#nav-languages">
<span className={"flag-icon flag-icon-" + iso2}></span> {activeLanguage}
</a>
);
}
export default PrimaryNav;

How to change the active class in a navbar in react

Problem:
I am creating a React web application. In there I have created a side navbar like this.
import React, { PureComponent } from "react";
import imagine from "../../../assets/img/sidebar-2.jpg";
class Sidebar extends PureComponent {
constructor(props) {
super(props);
this.state = {
width: window.innerWidth,
activeTabClassName: "tab1"
};
}
// activeRoute(routeName) {
// return this.props.location.pathname.indexOf(routeName) > -1 ? "active" : "";
// }
updateDimensions() {
this.setState({ width: window.innerWidth });
}
componentDidMount() {
this.updateDimensions();
window.addEventListener("resize", this.updateDimensions.bind(this));
}
render() {
const sidebarBackground = {
backgroundImage: "url(" + imagine + ")"
};
return (
<div className="sidebar" data-image={imagine} id="sidebar">
<div className="sidebar-background" style={sidebarBackground} />
<div className="sidebar-wrapper">
<div className="logo">
<a href="/" className="simple-text">
<img
src="../../images/favicon.png"
style={{ maxHeight: "50px" }}
/>
Trafficfine
</a>
</div>
<ul className="nav">
<li className="nav-item active">
<a className="nav-link" href="/admin/dashbord">
<i className="fas fa-tachometer-alt" />
<p>Dashboard</p>
</a>
</li>
<li className="nav-item">
<a className="nav-link" href="/admin/officers">
<i className="fas fa-briefcase" />
<p>Officers</p>
</a>
</li>
<li>
<a className="nav-link" href="/admin/offences">
<i className="fas fa-times-circle" />
<p>Offences</p>
</a>
</li>
<li>
<a className="nav-link" href="/admin/drivers">
<i className="fas fa-bus-alt" />
<p>Drivers</p>
</a>
</li>
</ul>
</div>
</div>
);
}
}
export default Sidebar;
I want to change the active class dynamically when a user is clicking on the nav Item and add some styling to the active class. I saw some similar questions have been asked on the stack overflow and I tried those example. But through those, I was unable to achieve that. Can someone help me to solve my problem by modifying
my code? Thank you.
You already have your target class in state, you just need to add it like this
<div className={"sidebar " + this.state.activeTabClassName} data-image={imagine} id="sidebar">
And call this.setState( {activeTabClassName: "newActiveClass"} ) when you want to change it.

Resources