NextJs router seems very slow - reactjs

The problem is about that is taking long time to response another route. It seems next router's error and it can cause by this ("getServerSideProps"). How can I change with this code to another or did I need to change react router instead? This is index which used ("getServerSideProps") -
import axios from 'axios';
import VideoCard from '../components/VideoCard';
import { BASE_URL } from '../utils';
import { Video } from '../types';
import NoResults from '../components/NoResults';
interface IProps {
videos: Video[];
}
const Home = ({ videos }: IProps) => {
return (
<div className='flex flex-col gap-10 videos h-full'>
{videos.length
? videos?.map((video: Video) => (
<VideoCard post={video} isShowingOnHome key={video._id} />
))
: <NoResults text={`No Videos`} />}
</div>
);
};
export default Home;
export const getServerSideProps = async ({
query: { topic },
}: {
query: { topic: string };
}) => {
let response = await axios.get(`${BASE_URL}/api/post`);
if(topic) {
response = await axios.get(`${BASE_URL}/api/discover/${topic}`);
}
return {
props: { videos: response.data },
};
};
This is from another code with that used next router
import React, { useState } from 'react';
import { NextPage } from 'next';
import { useRouter } from 'next/router';
import Link from 'next/link';
import { AiFillHome, AiOutlineMenu } from 'react-icons/ai';
import { ImCancelCircle } from 'react-icons/im';
import SuggestedAccounts from './SuggestedAccounts';
import Discover from './Discover';
import Footer from './Footer';
import useAuthStore from '../store/authStore';
const Sidebar: NextPage = () => {
const [showSidebar, setShowSidebar] = useState<Boolean>(true);
const { pathname } = useRouter();
const { fetchAllUsers, allUsers }: any = useAuthStore();
const activeLink = 'flex items-center gap-3 hover:bg-primary p-3 justify-center xl:justify-start cursor-pointer font-semibold text-[#F51997] rounded';
const normalLink = 'flex items-center gap-3 hover:bg-primary p-3 justify-center xl:justify-start cursor-pointer font-semibold rounded';
return (
<div>
<div
className='block xl:hidden m-2 ml-4 mt-3 text-xl'
onClick={() => setShowSidebar(!showSidebar)}
>
{showSidebar ? <ImCancelCircle /> : <AiOutlineMenu />}
</div>
{showSidebar && (
<div className='xl:w-400 w-20 flex flex-col justify-start mb-10 border-r-2 border-gray-100 xl:border-0 p-3 '>
<div className='xl:border-b-2 border-gray-200 xl:pb-4'>
<Link href='/'>
<div className={pathname === '/' ? activeLink : normalLink}>
<p className='text-2xl'>
<AiFillHome />
</p>
<span className='capitalize text-xl hidden xl:block'>
For You
</span>
</div>
</Link>
</div>
<Discover />
<SuggestedAccounts
fetchAllUsers={fetchAllUsers}
allUsers={allUsers}
/>
<Footer />
</div>
)}
</div>
);
};
export default Sidebar;

Related

Sanity doesnt connect blog post?

i have an issue with sanity, but i think the problem is the code doesnt fetch the blog post. any idea?
import { useState, useEffect } from "react"
import { Link, useParams } from "react-router-dom"
import client from "../client"
import { PortableText } from '#portabletext/react'
export default function SinglePost() {
const [singlePost, setSinglePost] = useState([])
const [isLoading, setIsLoading] = useState(true)
const { slug } = useParams()
useEffect(() => {
client
.fetch(
`*[slug.current == "${slug}"] {
title,
body,
mainImage {
asset -> {
_id,
url
},
alt
}
}`
)
.then((data) => setSinglePost(data[0]))
setIsLoading(false)
}, [slug])
return (
<>
{isLoading ? (
Loading...
) : (
{singlePost.title}
{singlePost.mainImage && singlePost.mainImage.asset && (
)}
<div className="block__content">
<PortableText
value={singlePost.body}
projectId="*******"
dataset="production"
/>
</div>
<button>
<Link
to="/blog"
className="py-2 px-6 rounded shadow text-white bg-black hover:bg-transparent border-2 border-black transition-all duration-500 hover:text-black font-bold"
>
Read more articles
</Link>
</button>
</section>
)}
</>
)
}

how to map and display a set of object from a data collection from mongodb in nextjs

I am currently trying to filter products of the same category and display on the page when the user clicks on a particular category. I've done this with the product detail page but I can't seem to figure out the right way to pull out all categories on the category page. Nothing expept the layout displays on the category page when redirected. Please help me using the following code
/pages/category/[slug].js
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import { useContext } from 'react';
import { toast } from 'react-toastify';
import Layout from '../../components/Layout';
import ProductItem from '../../components/ProductItem';
import Product from '../../components/models/Product';
import db from '../../utils/db';
import { Store } from '../../utils/Store';
import { useRouter } from 'next/router';
export default function Home({ products }) {
const router = useRouter();
const { state, dispatch } = useContext(Store);
const { cart } = state;
const addToCartHandler = async (product) => {
const existItem = cart.cartItems.find((x) => x.slug === product.slug);
const quantity = existItem ? existItem.quantity + 1 : 1;
const { data } = await axios.get(`/api/products/${product._id}`);
if (data.countInStock < quantity) {
return toast.error('Sorry. Product is out of stock');
}
dispatch({ type: 'CART_ADD_ITEM', payload: { ...product, quantity } });
toast.success('Product added to the cart');
};
const buyNowHandler = async (product) => {
const existItem = cart.cartItems.find((x) => x.slug === product.slug);
const quantity = existItem ? existItem.quantity + 1 : 1;
const { data } = await axios.get(`/api/products/${product._id}`);
if (data.countInStock < quantity) {
return toast.error('Sorry. Product is out of stock');
}
dispatch({ type: 'CART_ADD_ITEM', payload: { ...product, quantity } });
toast.success('Product added to the cart');
router.push('/cart');
};
return (
<Layout title="Home Page">
<div className="products-heading">
<h2>Best Selling Products</h2>
<p>Smoke accessories of many variations</p>
</div>
<div className="products-container">
{products.map((item, index) => (
<ProductItem
product={item}
key={index}
addToCartHandler={addToCartHandler}
buyNowHandler={buyNowHandler}
></ProductItem>
))}
</div>
</Layout>
);
}
export async function getServerSideProps(params) {
const { category } = params;
await db.connect();
const products = await Product.find().lean();
return {
props: {
products: products.filter((productItem) =>
productItem.category.includes(category)
),
},
};
}
/components/Layout.jsx
import React, { useContext, useEffect, useState } from 'react';
import Head from 'next/head';
import Link from 'next/link';
import { Menu } from '#headlessui/react';
import Category from './Category';
export default function Layout() {
return (
<>
<Head>
<title>
{title ? title + ' - Puffizzy' : 'Puffizzy Accessories'}
</title>
<meta name="description" content="Puffizzy Ecommerce Website" />
<link rel="icon" href="/puffizzy_logo.png" />
</Head>
<ToastContainer position="bottom-center" limit={1} />
<div className="flex min-h-screen flex-col justify-between">
<header>
<nav className="flex h-24 justify-between item-center px-4 py-4">
<Link href="/">
<img src="/puffizzy_logo_name.png" alt="" className="w-24" />
</Link>
<div className="navbar-right">
<div className="categories">
<Menu as="div" className="relative inline-block z-10 bg-white">
<Menu.Button className="">Categories</Menu.Button>
<Menu.Items className="absolute right-0 w-full origin-top-right shadow-lg">
<Menu.Item>
<Category />
</Menu.Item>
</Menu.Items>
</Menu>
</div>
</div>
</nav>
</header>
<main className="container m-auto mt-4 px-4">{children}</main>
<footer className="flex h-10 justify-center items-center shadow-inner">
<p>Footer</p>
</footer>
</div>
</>
);
}
/componenets/Category.jsx
import Link from 'next/link';
import React from 'react';
export default function Category() {
return (
<div className="bg-gray-200">
{['Lighter', 'Crusher', 'Pipe', 'Roller', 'Hookah', 'All'].map(
(item, index) => (
<div
key={index}
className="flex p-2 hover:bg-gray-100"
>
<Link href={`/category/${item}`}>{item}</Link>
</div>
)
)}
</div>
);
}

Building a react project, if user has already subscribed then it should redirect to homepage but if user sign up then pop up planPage

I've used redux to maintain state if user has already subscribed but on reload, already subscribed users are also redirected to planPage instead of homePage because on reload state sets back to initial null state how should i do it then ?
This is my App.jsx
import { useEffect, useState } from "react";
import DetailPage from "./pages/DetailPage";
import ProfilePage from "./pages/ProfilePage";
import HomePage from "./pages/HomePage";
import LoginPage from "./pages/LoginPage";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import { useSelector, useDispatch } from "react-redux";
import { selectUser, login, logout } from "./features/userSlice";
import PlanPage from "./pages/PlanPage";
import { getDocs } from "firebase/firestore";
import { auth, users } from "./firebase";
import { selectSubscription } from "./features/subscriptionSlice";
function App() {
const user = useSelector(selectUser);
const isSubscribed = useSelector(selectSubscription);
const dispatch = useDispatch(); //hook to access redux dispatch function
useEffect(() => {
const unsubscribe = auth.onAuthStateChanged((userAuth) => {
// observe the state change in user's sign in activity
if (userAuth) {
//logged in
dispatch(login({ uid: userAuth.uid, email: userAuth.email }));
} else {
//logged out
dispatch(logout());
}
});
return unsubscribe; // for cleanup the previous state
}, [dispatch]);
console.log(isSubscribed);
return (
<div>
<BrowserRouter>
{!user ? (
<LoginPage />
) : (
<>
{!isSubscribed ? (
<PlanPage />
) : (
<>
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="detailScreen" element={<DetailPage />} />
<Route path="profileScreen" element={<ProfilePage />} />
<Route path="planScreen" element={<PlanPage />} />
</Routes>
</>
)}
</>
)}
</BrowserRouter>
</div>
);
}
export default App;
planPage.jsx file
import React, { useState, useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { auth } from "../firebase";
import { logout } from "../features/userSlice";
import { AiOutlineCheck } from "react-icons/ai";
import { products, users } from "../firebase";
import { getDocs, setDoc, doc } from "firebase/firestore";
import Table from "../components/Table";
//import { BiLoaderAlt } from "react-icons/bi";
import {
showSubscriptionDetail,
selectSubscription,
} from "../features/subscriptionSlice";
import { useNavigate } from "react-router-dom";
export default function PlanPage() {
const navigate = useNavigate();
const subscription = useSelector(selectSubscription);
const [prod, setProducts] = useState([]); //useState() hook, sets initial state to an empty array
const [selectedPlan, setSelectedPlan] = useState(null);
useEffect(() => {
async function unsubscribe() {
const item = await getDocs(products);
const productItem = item.docs.map((doc) => ({
id: doc.id, //id and data pushed into productItems array
...doc.data(),
}));
setProducts(productItem);
setSelectedPlan(productItem[2]);
}
unsubscribe();
}, []);
const dispatch = useDispatch();
const handleClick = () => {
auth.onAuthStateChanged(() => {
dispatch(logout());
});
};
const manageSubscription = () => {
if (subscription) navigate("/");
navigate(-1);
};
async function setData(data) {
await setDoc(doc(users, `${auth.currentUser.email}`), {
productType: data,
email: auth.currentUser.email,
subscribed: true,
activateTime: new Date().toLocaleString(),
planEndTime: `${
new Date().getMonth() + 2
}/${new Date().getDate()}/${new Date().getFullYear()}`,
});
}
const subscribeToPlan = () => {
if (!auth) return;
dispatch(showSubscriptionDetail({ subscription: true }));
setData(selectedPlan?.name);
};
return (
<div>
<header className="border-b border-white/10 bg-[#141414] ">
<img
alt=""
src="https://rb.gy/ulxxee"
width={150}
height={90}
className="cursor-pointer object-contain"
onClick={manageSubscription}
/>
<button
className="text-lg font-medium hover:underline"
onClick={handleClick}
>
Sign Out
</button>
</header>
<main className="mx-auto max-w-5xl px-5 pt-28 pb-12 transition-all md:px-10">
<h1 className="mb-3 text-lg md:text-3xl font-medium">
Choose the plan that's right for you
</h1>
<ul>
<li className="flex items-center gap-x-2 text-sm md:text-lg">
<AiOutlineCheck className=" h-5 w-5 md:h-7 md:w-7 text-[#E50914]" />{" "}
Watch all you want. Ad-free.
</li>
<li className="flex items-center gap-x-2 text-sm md:text-lg">
<AiOutlineCheck className=" h-5 w-5 md:h-7 md:w-7 text-[#E50914]" />{" "}
Recommendations just for you.
</li>
<li className="flex items-center gap-x-2 text-sm md:text-lg">
<AiOutlineCheck className=" h-5 w-5 md:h-7 md:w-7 text-[#E50914]" />{" "}
Change or cancel your plan anytime.
</li>
</ul>
<div className="mt-4 flex flex-col space-y-4">
<div className="flex w-full items-center self-end md:w-3/5">
{prod.map((product) => (
<div
className={`planBox ${
selectedPlan?.id === product.id ? "opacity-100" : "opacity-60"
}`}
key={product.id}
onClick={() => setSelectedPlan(product)} //here if i have directly called the stateSetter i.e setSelectedPlan then it is getting called soon after the component mount stage, and keeps on rerender the state and getting stuck into loops. hence ()=> setSelected()
>
{product.name}
</div>
))}
</div>
<Table products={prod} selectedPlan={selectedPlan} />
<button
disabled={!selectedPlan}
className={`mx-auto w-11/12 rounded bg-[#E50914] py-4 text-xl shadow hover:bg-[#f6121d] md:w-[420px] `}
onClick={subscribeToPlan}
>
Subscribe
</button>
</div>
</main>
</div>
);
}
subscriptionSlice.jsx (redux-reducer code)
import { createSlice } from "#reduxjs/toolkit";
export const subscriptionSlice = createSlice({
name: "subscription",
initialState: {
subscription: null,
},
reducers: {
showSubscriptionDetail: (state, action) => {
state.subscription = action.payload;
},
},
});
export const { showSubscriptionDetail } = subscriptionSlice.actions;
export const selectSubscription = (state) =>
state.subscription.subscription?.subscription;
export const subscriptionReducer = subscriptionSlice.reducer;
I implemented this features just by defining a state(issubscribed) in App.js and have access to db. if subscription exist in firebase sent back a data if not it will stay null and you can have the simple logic in your routing.

How can I mock render the headless UI component in react testing?

I'm writing a test to render my App component in the child there's a dashboard component where I'm using headless UI it working fine on localhost but getting undefined components on rendering on test how can I render them?
I'm trying to mock the render but no success yet it always rendering as undefined
App.test
import { render } from '#testing-library/react';
import { SnackbarProvider } from 'notistack';
import React from 'react';
import { Provider } from 'react-redux';
import { MemoryRouter } from 'react-router-dom';
import { applyMiddleware, createStore } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension';
import thunk from 'redux-thunk';
import App from './App';
// import { rootReducer } from './store';
jest.mock('#headlessui/react', () => ({
...jest.requireActual('#headlessui/react'),
}));
describe('', () => {
function renderApp(
store = {},
// createStore(
// rootReducer,
// {},
// composeWithDevTools(applyMiddleware(thunk))
// ),
props = {}
) {
return render(
<SnackbarProvider>
<MemoryRouter>
{/* <Provider store={store}> */}
<App />
{/* </Provider> */}
</MemoryRouter>
</SnackbarProvider>
);
}
test('test render app component', async () => {
renderApp();
});
});
Component failing on test
import React, { Fragment, useState, useMemo, useEffect } from 'react';
import { Menu, Transition } from '#headlessui/react';
import { ChevronDownIcon } from '#heroicons/react/solid';
// import { useSelector, useDispatch } from 'react-redux';
// import types from '../../store/actions/types';
// NOTE - for ref this is happening globally now
// and it has the global styles taken out of it
// so it doesn't mess with other stuff hopefully
// import './tailwind-style.scss'
function classNames(...classes) {
return classes.filter(Boolean).join(' ');
}
const AdvertSwitch = () => {
console.log({ Menu, Transition });
// const dispatch = useDispatch()
const advertisersFromState = [
{
id: 1,
name: 'advertiser-one',
},
{
id: 2,
name: 'advertiser-two',
},
];
const advertisers = advertisersFromState;
const selectedAdvertiser = advertisersFromState[0];
const handleAdvertSwitch = (advertiser) => {
console.log('handle advertiser switch', advertiser);
};
const showMultiple = true;
const Single = () => {
return (
<div className="">
<div>{selectedAdvertiser?.name ?? 'loading...'}</div>
</div>
);
};
const Multiple = () => {
// } else {
return (
<div className="w-full bg-gray-200 flex justify-end">
<Menu as="div" className="ml-3 z-10 relative inline-block text-left">
<div>
<Menu.Button className="inline-flex justify-center w-full rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-transparent ">
{selectedAdvertiser?.name ?? 'loading...'}
<ChevronDownIcon
className="-mr-1 ml-2 h-5 w-5"
aria-hidden="true"
/>
</Menu.Button>
</div>
<Transition
as={Fragment}
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<Menu.Items className="origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 focus:outline-none">
<hr className="h-1 p-0 m-0" />
<div className="py-1">
{advertisers.map((advertiser) => {
return (
<Menu.Item key={advertiser.id}>
{({ active }) => (
<div
className={classNames(
active
? 'bg-gray-100 text-gray-900'
: 'text-gray-700',
'block px-4 py-2 text-sm'
)}
onClick={() => handleAdvertSwitch(advertiser)}
>
{advertiser?.name ?? 'loading...'}
</div>
)}
</Menu.Item>
);
})}
</div>
</Menu.Items>
</Transition>
</Menu>
</div>
);
};
return (
<div className="mr-2">
{showMultiple && <Multiple />}
{!showMultiple && <Single />}
</div>
);
};
export default AdvertSwitch;
Failing Test Snap

React router useHistory

I want when I press on the button it redirects me to the payment page.
import React,{useHistory, useState} from 'react'
import data from './data.json'
function GLC() {
let history = useHistory();
function handleClick() {
history.push("/payment");
}
return (
<div >
{data.map((postData) =>{
console.log(postData)
return(
<div key=
{postData.id}>
<div className='absolute '>
<img className='w-screen object-contain'src="./ModImages/Gclass.jpg"></img>
<h1 className='absolute ml-24 md:text-5xl sm:text-5xl top-8'>Class G</h1>
<h1 className='absolute text-base font-mono ml-24 top-24'>$43,600</h1>
<button onClick={handleClick} className=' absolute text-black-600 h-10 top-24 ml-24 mt-32 bg-
white w-36 rounded-full focus:outline-none focus:ring-2 focus:ring-gray-600'>BuyNow</button>
</div>
</div>
)
})
}
</div>
)
}
export default GLC
// Make sure you alreadly installed the react-router-dom package.
import { useHistory } from 'react-router-dom';
function GLC() {
const history = useHistory();
function handleClick() {
history.push("/payment");
}
// ...
}
Then you can work .

Resources