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}/>
</>
)
}
Related
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 am trying to make a simple hotel reservation web app in react. Here is what I want to achieve. A user selects room, adults, and children in number and reserve he's/her own hotels. The following screenshot depicts exactly what I want to do.
As you see from the above screenshot, when I click children's Increment + button, I wanted to append a div having children and their age. In the above screenshot, as I Incremented children value 2 times Two divs with children and their age has been appended.
I already design the component as follows. I want the logic here to apply.
Here is my Component code, I use tailwindcss for styling
import React, { useState } from "react";
import rateIcon from "../../../assets/rate-cons.PNG";
import {
CheckIcon,
InformationCircleIcon,
WifiIcon,
ParkingIcon,
HeartIcon,
SwitchVerticalIcon,
AdjustmentsIcon,
MapIcon,
MinusIcon,
PlusIcon,
} from "#heroicons/react/outline";
import mapImage from "../../../assets/map.PNG";
import { LocationMarkerIcon } from "#heroicons/react/solid";
import DatePickers from "../DatePicker/DatePicker";
import {
HotelOutlined,
PeopleAltOutlined,
RoomOutlined,
RoomService,
} from "#material-ui/icons";
import {
ChildFriendly,
FamilyRestroomOutlined,
FamilyRestroomRounded,
} from "#mui/icons-material";
const Hero = () => {
const [rooms, setRooms] = useState(0);
const [show, setShow] = useState(false);
const showGuestInfo = () => setShow(!show);
const addRooms = () => {
setRooms(rooms + 1);
};
const removeRooms = () => {
if (rooms > 1) {
setRooms(rooms - 1);
} else {
setRooms(rooms);
}
};
return (
<div className="p-3 flex w-full flex flex-col relative">
<div className="flex flex-col border-b border-gray">
<div className="p-2 flex justify-between items-center ">
<div className="flex text-sm items-center space-x-2">
<HotelOutlined />
<p>Rooms</p>
</div>
<div className="flex space-x-4 border p-2">
<p>
<MinusIcon
// onClick={removeRooms}
className="bg-gray-light h-6 cursor-pointer"
/>
</p>
<p>{rooms}</p>
<PlusIcon
// onClick={addRooms}
className=" bg-gray-light h-6 cursor-pointer"
/>
</div>
</div>
<div className="p-2 flex justify-between items-center">
<div className="flex text-sm items-center space-x-2">
<PeopleAltOutlined />
<p>Adults</p>
</div>
<div className="flex space-x-4 border p-2">
<p>
<MinusIcon
// onClick={removeRooms}
className="h-6 bg-gray-light cursor-pointer"
/>
</p>
<p>{rooms}</p>
<PlusIcon
// onClick={addRooms}
className="h-6 bg-gray-light cursor-pointer"
/>
</div>
</div>
<div className="p-2 flex justify-between items-center">
<div className="flex text-sm items-center space-x-2">
<FamilyRestroomOutlined />
<p>Childrens</p>
</div>
<div className="flex space-x-4 border p-2">
<p>
<MinusIcon
onClick={removeRooms}
className="h-6 bg-gray-light cursor-pointer"
/>
</p>
<p>{rooms}</p>
<PlusIcon
onClick={addRooms}
className="h-6 bg-gray-light cursor-pointer"
/>
</div>
</div>
</div>
<div className="border-t p-2 border-gray ">
<button className="p-2 border-t border-gray bg-black w-full text-white">
Update
</button>
</div>
</div>
);
};
How can I build this logic?
The correct way to do this in React is to set the state of your component (or its parent). Then when you render the component, you use the state to decide what to render. So you don't "append" a div as much as you decide that you need a div at a certain spot due to the state.
In this case, you might have a list of children's ages as state. Clicking on the + button will add an element to this list, probably defaulting to 0. Then for each child's age, you render a <div> and a <select> with that age. If the age is 0, then you have a message telling the user to select an age. When the user selects an age, you update the list at the correct position with that age.
Note that this can be implemented as a separate component to simplify the code in the top-level view.
The key thing here is that you never manipulate the DOM directly like you would with pure JavaScript or JQuery. Instead, you keep some data and use it to decide what to render.
Since you don't have example, here is a repro on Stackblitz on how you can do it, and here is the code :
import React, { Component } from 'react';
import { render } from 'react-dom';
const App = () => {
const [children, setChildren] = React.useState(0);
return (
<div>
Children :{' '}
<input
type="number"
value={children}
onChange={(e) => setChildren(Number(e.target.value))}
/>
{Array.from(Array(Number(children)).keys()).map((child, index) => (
<div key={index}>
child of <input type="number" /> years old
</div>
))}
</div>
);
};
render(<App />, document.getElementById('root'));
The state children store the number of children. We then just render as many div as this number by creating an array and mapping over it with this particular line :
Array.from(Array(Number(children)).keys())
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>
)
}
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.
const Navbar = ({ toggle, isOpen }) => {
const data = localStorage.getItem("theme");
return (
<div className="bg-gray-300 shadow-md relative z-30 dark:bg-gray-800 transition duration-300 ease-in-out">
<div className="mx-auto p-4 max-w-7xl">
<nav>
<div className="flex justify-between items-center">
<Link to="/" className="mojLogo">
<SvgLogo />
</Link>
<div className="flex items-center">
<NavLinks />
<div className="cursor-pointer md:hidden" onClick={toggle}>
<Hamburger
toggled={isOpen}
color={data === "light" ? "#ff0" : "#dc0000"}
/>
</div>
</div>
</div>
</nav>
</div>
</div>
);
};
export default Navbar;
Here you have a piece of code that works when the first color page is read is set based on the values in local Storage that are dark or light. I'm interested in how to change colors when changing values in local Storage without refreshing the page.
First thing that comes to mind is useLocalStorage React hook (https://usehooks.com/useLocalStorage/).
I think it will get the job done for you.