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>
)
}
Related
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
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">
I'm trying to pass props to a new page in Next JS.
I'm mapping through an array, each item should link to a page where I can use data from the array as props:
{mentors.map((mentor) => (
<Link href="/developers/developer">
<div
key="name"
className="flex flex-col text-green-50 bg-gray-800 rounded-md p-6 gap-3 border border-gray-800 hover:border-gray-700 cursor-pointer"
>
<div className="flex justify-between items-center ">
<div className="flex items-center gap-2">
<img src={mentor.pic} className="rounded-full w-10" />{" "}
{mentor.name}
</div>
{mentor.timeZone}
</div>
<p className="text-gray-300">
I am a full-stack dev with over 8 years experience in
making software and web-apps.
</p>
<div className="flex gap-2 items-center">
Can teach:
{mentor.languages.map((language) => (
<p
key={language}
className="px-3 py-1 bg-gray-900 rounded-full max-w-max text-sm"
>
{language}
</p>
))}
</div>
</div>
</Link>
))}
This is the page:
export default function DeveloperPage({ name, picture }) {
return (
<>
{name}
<img src={picture}/> </>)}
I need to pass that {name} and {picture} prop from the item in the array to the new page.
What's the most elegant way to do it in Next?
Thanks!
You can pass it trough URL query
Like this
<Link href={`/developers/developer?name=${mentor.name}&picture=${mentor.picture}`}>
and you can use useRouter on your DeveloperPage to get its values
import { useRouter } from 'next/router'
export default function DeveloperPage() {
const router = useRouter()
const {name, picture} = router.query // <-- passed datas are in here
return (
<>
{name}
<img src={picture}/>
</>
)
}
I'm trying too split my application into multiple components, and I'm trying to create a dashboard component, however, how do I go about implementing next-auth within the component, previously I had getServerSideProps but as this is a component I can't do that.
Here is my component
import {
SearchIcon,
BellIcon,
UserCircleIcon,
ChevronDownIcon,
UserIcon,
LogoutIcon
} from '#heroicons/react/outline';
import { signOut } from 'next-auth/client';
export default function Navigation(...session) {
return (
<>
<div className="py-6 px-8 lg:h-16 lg:flex justify-between items-center bg-blue-700 text-white">
<div className="flex-1">
<div className="lg:pr-4 lg:py-4">
<label htmlFor="search" className="sr-only">
Search
</label>
<div className="relative">
<div className="pointer-events-none absolute inset-y-0 left-0 pl-3 flex items-center">
<SearchIcon className="h-5 w-5 text-white" aria-hidden="true" />
</div>
<input
id="search"
name="search"
className="block w-full bg-blue-800 border border-blue-800 rounded-md py-2 pl-10 pr-3 text-sm placeholder-white focus:outline-none focus:ring-1 focus:ring-white focus:border-white sm:text-sm"
placeholder="Search"
type="search"
/>
</div>
</div>
</div>
<div className="relative flex items-center justify-center mt-8 lg:mt-0">
<div className="relative mr-6">
<BellIcon className="w-5" />
<small className="text-xs absolute -top-1 -right-2 -mt-2 bg-red-500 rounded-full py-0.5 px-1.5">
1
</small>
</div>
<details className="relative">
<summary className="flex items-center">
<UserCircleIcon className="w-5 mr-2" />
<h2>
{session.user.firstname} {session.user.lastname}
</h2>
<ChevronDownIcon
className="ml-2 flex-shrink-0 h-4 w-4 text-blue-200"
aria-hidden="true"
/>
</summary>
<div className="w-full mt-4 pb-4 absolute shadow-lg flex flex-col justify-center px-2 space-y-1 bg-blue-700">
<Link href="/dashboard/myprofile">
<a className="bg-blue-800 text-white hover:bg-blue-600 flex items-center px-2 py-2 text-sm font-medium rounded-md">
<UserIcon className="w-5 h-5 mr-2" />
Profile
</a>
</Link>
<Link href="#">
<a
onClick={signOut}
className="bg-blue-800 text-white hover:bg-blue-600 flex items-center px-2 py-2 text-sm font-medium rounded-md">
<LogoutIcon className="w-5 h-5 mr-2" />
Sign out
</a>
</Link>
</div>
</details>
</div>
</div>
</>
);
}
Currently what I'm getting is the following
TypeError: Cannot read properties of undefined (reading 'firstname')
edit #1
Here is my _app.js [UPDATED]
import Head from 'next/head';
import { Provider } from 'next-auth/client';
// assets
import '../styles/global.css';
import '../javascripts/app.js';
// components
import Footer from './components/Footer';
function MyApp({ Component, pageProps }) {
return (
<>
<Head>
<meta name="theme-color" content="#1E40AF" />
</Head>
<section className="flex flex-col min-h-screen">
<Provider session={pageProps.session}>
<Component {...pageProps} className="flex-1" />
</Provider>
</section>
<Footer />
</>
);
}
export default MyApp;
To fix this I did the following
_app.js - Now using provider to share the session across all pages.
import Head from 'next/head';
import { Provider } from 'next-auth/client';
// assets
import '../styles/global.css';
import '../javascripts/app.js';
// components
import Footer from './components/Footer';
function MyApp({ Component, pageProps }) {
return (
<>
<Head>
<meta name="theme-color" content="#1E40AF" />
</Head>
<section className="flex flex-col min-h-screen">
<Provider session={pageProps.session}>
<Component {...pageProps} className="flex-1" />
</Provider>
</section>
<Footer />
</>
);
}
export default MyApp;
and for the component I now have the following
import {
SearchIcon,
BellIcon,
UserCircleIcon,
ChevronDownIcon,
UserIcon,
LogoutIcon
} from '#heroicons/react/outline';
import { useSession, signOut } from 'next-auth/client';
import Link from 'next/link';
export default function Navigation() {
const [session, loading] = useSession()
return (
<>
<div className="py-6 px-8 lg:h-16 lg:flex justify-between items-center bg-blue-700 text-white">
<div className="flex-1">
<div className="lg:pr-4 lg:py-4">
<label htmlFor="search" className="sr-only">
Search
</label>
<div className="relative">
<div className="pointer-events-none absolute inset-y-0 left-0 pl-3 flex items-center">
<SearchIcon className="h-5 w-5 text-white" aria-hidden="true" />
</div>
<input
id="search"
name="search"
className="block w-full bg-blue-800 border border-blue-800 rounded-md py-2 pl-10 pr-3 text-sm placeholder-white focus:outline-none focus:ring-1 focus:ring-white focus:border-white sm:text-sm"
placeholder="Search"
type="search"
/>
</div>
</div>
</div>
<div className="relative flex items-center justify-center mt-8 lg:mt-0">
<div className="relative mr-6">
<BellIcon className="w-5" />
<small className="text-xs absolute -top-1 -right-2 -mt-2 bg-red-500 rounded-full py-0.5 px-1.5">
1
</small>
</div>
<details className="relative">
<summary className="flex items-center">
<UserCircleIcon className="w-5 mr-2" />
{ session &&
<h2>
{session.firstname} { session.lastname}
</h2>
}
<ChevronDownIcon
className="ml-2 flex-shrink-0 h-4 w-4 text-blue-200"
aria-hidden="true"
/>
</summary>
<div className="w-full mt-4 pb-4 absolute shadow-lg flex flex-col justify-center px-2 space-y-1 bg-blue-700">
<Link href="/dashboard/myprofile">
<a className="bg-blue-800 text-white hover:bg-blue-600 flex items-center px-2 py-2 text-sm font-medium rounded-md">
<UserIcon className="w-5 h-5 mr-2" />
Profile
</a>
</Link>
<Link href="#">
<a
onClick={signOut}
className="bg-blue-800 text-white hover:bg-blue-600 flex items-center px-2 py-2 text-sm font-medium rounded-md">
<LogoutIcon className="w-5 h-5 mr-2" />
Sign out
</a>
</Link>
</div>
</details>
</div>
</div>
</>
);
}
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>