Prevent React component re render when route change - reactjs

I am using react-router-dom.
let's assume I have 2 pages like Homepage and Profile Page. Both pages have a component named a Header.
In the Header component, using useEffect React Hook I am calling a fetch request on my back-end server and fetching logged-in user data. API returns username, avatar image, etc. (that's not a problem)
thing is that. when I jump from "Homepage" to "profile page", the Header component, re-render and send the request to the server again. this occurs every time when I jump from the homepage to the profile page or profile page to the home page. and the data displayed on the Header keeps loading until the fetched request succeeds.
I want something like Youtube.
Header Component
import {useState , useEffect} from 'react'
import Logo from './imgs/logo.png'
import {Link} from 'react-router-dom'
import { FaArrowRight , FaServicestack , FaFirstOrder} from "react-icons/fa";
import { BsPersonCheck , AiOutlineContacts } from "react-icons/all";
const ShowOrHideNav = ()=>{
var nav = document.getElementById('NavBarSpingbuck')
nav.classList.toggle('hidden')
}
const Header = () =>{
const [loggedIn , setLoggedIn] = useState(false)
const [user_data , setUserData] = useState(undefined)
const Logout = () =>{
localStorage.removeItem('sb_auth_token')
UpdateHeader()
}
const UpdateHeader = () =>{
const auth_token = localStorage.getItem('sb_auth_token')
if(auth_token){
console.log('sending request')
fetch(
'https://dummy_API_URL.dummy_domain.com/authentication/user/',
{
headers:{
Authorization : 'Token ' + auth_token,
},
}
)
.then(response => response.json())
.then(resp_data =>{
if(resp_data.status == 200){
setUserData(resp_data.data)
}
})
.catch(error =>{
console.log(error)
console.log('error')
})
setLoggedIn(true)
}
else{
setLoggedIn(false)
}
}
useEffect(()=>{
UpdateHeader()
} , [])
return(
<div className=' fixed top-0 z-50 w-full shadow bg-black bg-opacity-75 px-5' style={{backdropFilter:'blur(18px)'}}>
<div className='container py-2 flex items-center justify-between mx-auto relative'>
<div className='w-8 h-8 md:hidden flex flex-col justify-evenly items-end cursor-pointer group ' onClick={ShowOrHideNav}>
<span className='w-2 h-1 bg-white block rounded-full transition-all delay-150 duration-300 group-hover:w-8'></span>
<span className='w-4 h-1 bg-white block rounded-full transition-all duration-300 group-hover:w-8'></span>
<span className='w-8 h-1 bg-white block rounded-full '></span>
</div>
<div>
<Link to='/'>
<img src={Logo} className='w-32 ' />
</Link>
</div>
<div className='px-5'>
<ul className='items-center hidden p-4 md:p-0 md:flex absolute md:relative top-full md:top-0 w-full md:w-auto z-50 left-0 bg-white md:bg-transparent rounded-lg md:rounded-none transition-all duration-300' style={{animationIterationCount:1}} id='NavBarSpingbuck'>
<li className='hover:scale-110 duration-150 transform px-4 mb-4 md:mb-0' >
<Link className='flex flex-col items-center text-gray-800 md:text-white'>
<p>Jobs</p>
</Link>
</li>
<li className='hover:scale-110 duration-150 transform px-4 mb-4 md:mb-0' >
<Link className='flex flex-col items-center text-gray-800 md:text-white'>
<p>Services</p>
</Link>
</li>
<li className='hover:scale-110 duration-150 transform px-4 mb-4 md:mb-0' >
<Link className='flex flex-col items-center text-gray-800 md:text-white'>
<p>Place Order</p>
</Link>
</li>
<li className='hover:scale-110 duration-150 transform px-4 mb-4 md:mb-0' >
<Link className='flex flex-col items-center text-gray-800 md:text-white'>
<p>About</p>
</Link>
</li>
<li className='hover:scale-110 duration-150 transform px-4 mb-4 md:mb-0' >
<Link className='flex flex-col items-center text-gray-800 md:text-white'>
<p>Contact</p>
</Link>
</li>
</ul>
</div>
<div className='account_bar'>
{
loggedIn?
<div className='flex items-center cursor-pointer group relative py-1'>
<div className='mr-3 rounded-full w-10 h-10 bg-center bg-cover' style={{backgroundImage:'url(https://pixinvent.com/materialize-material-design-admin-template/app-assets/images/user/12.jpg)'}}>
</div>
{
user_data && user_data.username ?
<p className='text-white'>{user_data.username}</p>: <p className='text-white'>User</p>
}
<div className='bg-white rounded-md py-2 w-28 absolute top-full shadow-2xl hidden group-hover:block'>
<ul>
<li className='px-2 py-1 hover:bg-blue-100'>
<Link className='block' to='/profile/' >Profile</Link>
</li>
<li className='px-2 py-1 hover:bg-blue-100' onClick={()=>{Logout()}}>
Logout
</li>
</ul>
</div>
</div>
:
<Link to='/authentication/login/' >
<div className='bg-yellow-600 py-0.5 px-2 rounded flex items-center justify-center hover:bg-yellow-700 transition-all duration-300'>
<p className='text-white pr-1'>Sign in</p>
<FaArrowRight className='text-white text-sm' />
</div>
</Link>
}
</div>
</div>
</div>
)
}
export default Header

You can render your Header component on its own route, separate from the route rendering either the home or profile pages. Use an array of paths you want the header component's Route to match. Presuming "/" is your homepage then you may also want to specify the exact prop so "/" doesn't match every path you have. This all, of course, also assumes the header component is rendered before all other content on the page for each of the home and profile pages.
Example:
<Router>
<Route exact path={["/profile", "/"]} component={Header} />
<Switch>
<Route path="/profile" component={ProfilePage} />
<Route path="/" component={HomePage" />
</Switch>
</Router>

Extract the Header component and place it on the same level with the Switch component.
<Router>
<Header />
<Switch>
<Route path="/">
<Home />
</Route>
<Route path="/profile">
<Profile />
</Route>
</Switch>
</Router>

Related

Portfolio react js mapping error for project cards

import React from 'react'
import net from '../assets/netflix.png'
const Porfolio = () => {
const Projects = [
{
id:1,
title:"Netflix Clone",
desc:"Netflix Landing Page Clone using React JS and Tailwind CSS with Authentication Feature using Firebase",
imgLink:net,
codeLink:"https://github.com/codegoggins/netflix-clone",
projectLink:"https://netflix-clone-13127.firebaseapp.com/"
}
]
return (
<div
className='px-20 py-4'>
<p
className='text-white text-4xl'
>Projects</p>
{/* PROJECT CARDS */}
<div
className='mt-8 flex flex-col justify-center items-center md:flex md:items-start'
>
{
Projects.map(({id,title,desc,imgLink,codeLink,projectLink})=>(
<>
{/* SINGLE CARD */}
<div className='w-[340px] h-auto relative group md:w-[500px]'>
{/* OVERLAY */}
<div
className='bg-black/80 text-sm md:text-lg absolute flex top-0 bottom-0 h-full w-full rounded-lg overflow-hidden opacity-0 group-hover:opacity-100 transition-all duration-300'>
{/* PROJECT DETAILS */}
<div
className='text-white text-sm md:text-lg flex flex-col p-4 gap-3 md:gap-2 items-center justify-center'>
{/* TITLE */}
<p>{title}</p>
{/* DETAIL */}
<p>{desc}</p>
{/* BUTTONS */}
<div
className='flex gap-3 text-sm md:text-lg'>
<button
className='cursor-pointer font-semibold p-1.5 px-4 rounded-md bg-white text-black transition ease-linear duration-300'
>
Code
</button>
<button
className='cursor-pointer font-semibold p-1.5 px-2 rounded-md bg-white text-black transition ease-linear duration-300'>
See Project
</button>
</div>
</div>
</div>
{/* Image */}
<div className='rounded-lg overflow-hidden'>
<img src={imgLink} alt="" className='h-full w-full object-cover'/>
</div>
</div>
</>
))
}
</div>
</div>
)
}
export default Porfolio
I am getting error to add key , for that instead of react fragments, I
replace it with a div and give key to it but I am getting error. With
react fragments I don't get any error but I can't add key to it for
mapping.
I want the card details to be mapped on all the cards.
enter image description here
You should return inside mapping and provide a key for the root element.
for example,
{
products?.map(({ id, title, desc, imgLink, codeLink, projectLink }) => {
return (
<div key={id} className='w-[340px] h-auto relative group md:w-[500px]'>
//Your code here
</div>
)
})}
You can add:
<React.Fragment key={id}>
some code
</React.Fragment>
or remove the fragment and add the key to the first div inside the map

How to fix Navbar design in React ?? Is there any change for Navbar design in Tailwind?

Initially I made a project and there the Navbar was completely ok. But I want to use the same Navbar on similar kind of project. But while type or copy paste the code the design is completely change. Even after a lot of search I can't find the actual problem as well as the solution also.
Both having same CSS file as well. Then where the problem occurs ?? Is there any change happened for Tailwind CSS design ?? Kindly let me know.
Navbar of previous project :
Navbar of present project :
Even though all codes are same. I put all the Navbar code below.
import { HiMenuAlt4 } from 'react-icons/hi';
import { AiOutlineClose } from 'react-icons/ai';
import logo from '../../images/logo.png';
const NavbarItem = ({ title, classProps }) => {
return (
<li className={`mx-4 cursor-pointer ${classProps}`}>
{title}
</li>
)
}
const Navbar = () => {
const [toggleMenu, setToggleMenu] = useState(false); //Mobile View On or Not
return (
<nav className="w-full flex md:justify-center justify-between items-center p-4">
<div className="md:flex-[0.5] flex-initial justify-center items-center">
<img src={logo} alt="logo" className="w-32 cursor-pointer"/>
</div>
<ul className="text-white md:flex hidden list-none flex-row justify-between items-center flex-initial">
{["Buy","Sell","Transfer","Wallets","About Us"].map((item, index) => (
<NavbarItem key={item + index} title={item} />
))}
<li className="bg-[#3d4f79] py-2 px-7 mx-4 rounded-full cursor-pointer hover:bg-[#2546]">
SIGN IN
</li>
</ul>
{/* Mobile View */}
<div className="flex relative">
{toggleMenu
? <AiOutlineClose fontSize={28} className="text-white md:hidden cursor-pointer" onClick={() => setToggleMenu(false)} />
: <HiMenuAlt4 fontSize={28} className="text-white md:hidden cursor-pointer" onClick={() => setToggleMenu(true)} />
}
{toggleMenu && (
<ul
className="z-10 fixed top-0 -right-2 p-3 w-[70vw] h-screen shadow-2x1 md:hidden list-none
flex flex-col justify-start items-end rounded-md blue-glassmorphism text-white animate-slide-in"
>
<li className="text-xl w-full my-2">
<AiOutlineClose onClick={() => setToggleMenu(false)} />
</li>
{["Market","Exchange","Tutorials","Wallets"].map((item, index) => (
<NavbarItem key={item + index} title={item} classProps="my-2 text-lg"/>
))}
</ul>
)}
</div>
</nav>
);
}
export default Navbar;```
by adding classname navbar fixed <nav className="fixed w-full flex md:justify-center justify-between items-center p-4">

React Next Tailwind CSS - How to create a hyperlink around custom component

In my index.tsx I have
<Header/>
In my Header.js component, I am using a HeroIcon embedded component.
export default function Header() {
return (
<header className='flex flex-col sm:flex-row m-5 justify-between items-center h-auto'>
<div className='flex flex-grow justify-evenly max-w-2xl'>
<HeaderItem title='HOME' Icon={HomeIcon} />
<HeaderItem title='ACCOUNT' Icon={UserIcon} />
In my HeaderItem.js
export default function HeaderItem({Icon,title}) {
return (
<div className="flex flex-col items-center cursor-pointer group w-12 sm:w-20
hover:text-red">
<Icon className="h-8 mb-1 group-hover:animate-bounce"/>
<p className="opacity-0 group-hover:opacity-100 tracking-widest"> {title} </p>
</div>
)
}
As far as I understand, I can pass a ref from the Header to HeaderItem component via props and then use the Link tag.
How do I wrap that around without losing the animation?
OK so this works for me -
On Header.js
<HeaderItem title='HOME' Icon={HomeIcon} url="/"/>
On the HeaderItem.js
export default function HeaderItem({Icon,title, url}) {
return (
<Link href={url}>
<div className="flex flex-col items-center cursor-pointer group w-12 sm:w-20
hover:text-red">
<Icon className="h-8 mb-1 group-hover:animate-bounce"/>
<p className="opacity-0 group-hover:opacity-100 tracking-widest"> {title} </p>
</div>
</Link>
)
}

Building a blog with React & Sanity.io - (import/no-anonymous-default-export)

This is the code for my blog page.
import React, {useState, useEffect} from "react";
import { Link } from "react-router-dom";
import sanityClient from "../client.js"
export default function Post(){
const [postData, setPost] = useState(null);
useEffect(() => {
sanityClient
.fetch(`*[_type == "post"]{
title,
slug,
mainImage{
asset->{
_id,
url
},
alt
}
}
}`)
.then((data) => setPost(data))
.catch(console.error);
}, []);
return(
<main className="bg-blue-100 min-h-screen p-12">
<section className="container mx-auto">
<h1 className="text-5xl flex justify-center cursive">
Updates Page
</h1>
<h2 className="text-lg text-gray-600 flex justify-center mb-12">
School Updates
</h2>
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
{postData && postData.map((post, index) => (
<article>
<Link to={"/post/" + post.slug.current} key={post.slug.current}>
<span className="block h-64 relative rounded shadow leading-snug bg-white border-l-8 border-blue-400" key={index}>
<img src={post.mainImage.asset.url}
alt={post.mainImage.alt}
className="w-full h-full rounded-r object-cover absolute"
/>
<span className="block relative h-full flex justify-end items-end pr-4 pb-4">
<h3 className="text-grey-800 text-lg font-bold px-3 py-4 bg-blue-700 text-blue-100 bg-opacity-75 rounded">
{post.title}
</h3>
</span>
</span>
</Link>
</article>
))}
</div>
</section>
</main>
)
}
It compiles just fine but doesn't load in the blog posts from the sanity client.
because in the sanity schema "post.js" I get green underline on everything: "Assign object to a variable before exporting as module default eslint(import/no-anonymous-default-export)"
I've looked at the docs it points me at but I'm just not getting wha the issue is. It seems fine to me. Someone please tell me where I am going wrong.
Thanks in advance!
Fixed, had an extra } in the fetch which wasn't flagging because it was inside the backticks.

Post.js is not showing the blog post...Are there any errors here?

There should be a block of blog post here but its empty:
Please check the map and the other syntaxes, I am not getting it.
import React,{useState,useEffect} from "react";
import { Link } from "react-router-dom";
import sanityClient from "../client.js";
This is the export default function below
export default function Post(){
const [postData, setPost] = useState(null);
useEffect(() => {
sanityClient
.fetch(`*[_type =="post"]{
title,
slug,
mainImage{
asset->{
_id;
url
},
alt
}
}`)
.then((data) => setPost(data))
.catch(console.error);
},[]);
I think there is something missing in postData map.
return (
<main className="bg-green-100 min-h-screen p-12">
<section className="container mx-auto">
<h1 className="text-5xl flex justify-center cursive">Blog Posts Page</h1>
<h2 className="text-lg text-gray-600 flex justify-center mb-12">Welcome to my world!</h2>
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
{postData && postData.map((post,index) => (
<article>
<Link to={"/post/" + post.slug.current} key={post.slug.current}>
<span className="block h-64 relative rounded shadow leading-snug bg-white border-l-8 border-green-400" key={index}>
<img src={post.mainImage.asset.url} alt={post.mainImage.alt} className="w-full h-full rounded-r object-cover absolute" />
<span className="block relative h-full flex justify-end items-end pr-4 pb-4">
<h3 className="text-gray-800 text-lg font-blog px-3 py-4 bg-red-700 text-red-100 bg-opacity-75 rounded">{post.title}</h3>
</span>
</span>
</Link>
</article>
))}
</div>
</section>
</main>
)
}

Resources