props is undefined when passing from parent to component in next js - next.js

I have /pages/profile.js which calls the LovedOne element, passing values from props.
Debugging shows that these values are valid when passed
import React from "react";
import LovedOne from "../components/loved_one";
export const Profile = ({ loved_ones }) => {
const [session, loading] = useSession();
if (loading) return <div>loading...</div>;
if (!session) return <div>no session</div>;
return (
<Layout>
{session && (
<>
<img src={session.user.image} className="avatar" />
<h1>{session.user.name}</h1>
</>
)}
{loved_ones.map((loved_one, index) => (
<LovedOne
key={index}
firstname={loved_one.firstname}
surname={loved_one.surname}
email={loved_one.email}
/>
))}
<style jsx>{`
.avatar {
width: 220px;
border-radius: 10px;
}
`}</style>
</Layout>
);
};
However in /components/loved_one.js my props is undefined
import React, { useState, useRef } from "react";
export const LovedOne = ({ props }) => {
const [setActive, setActiveState] = useState("");
const [setHeight, setHeightState] = useState("0px");
const content = useRef();
function toggleAccordion() {
setActiveState(setActive === "" ? "active" : "");
setHeightState(
setActive === "active" ? "0px" : `${content.current.scrollHeight}px`
);
}
return (
<div>
<div className="row">
<button
className={`collection-item ${setActive}`}
onClick={toggleAccordion}
>
<i className="fas fa-plus teal-text"></i>
</button>
<div className="col s2">
{props.firstname} {props.surname}
</div>
<div className="col s2">{props.email}</div>
</div>
<div ref={content} style={{ maxHeight: `${setHeight}` }}>
<span>some stuff</span>
</div>
</div>
);
};
export default LovedOne;
I've tried passing single variables, and passing the entire loved_ones object. I get the same problem.
Any help much appreciated!

Have you tried passing props instead of {props} ?
lose brackets, try this way:
export const LovedOne = (props) => {

Related

unable to dispacth a action to the store in redux

in checkOut js im unable to access the data inside the items arrey but i can access the length how is it possible i added 3 items i can see the items.lenth but when try to use items.map its not working showing error:
TypeError: Cannot read properties of undefined (reading 'image')
store.ts
import { configureStore } from "#reduxjs/toolkit";
import basketReducer from "./basketSlice";
//this is redux like a global store to store users items data
//when users put the items in the shopping cart
export const store = configureStore({
reducer: {
basket: basketReducer,
},
});
busketSlice.ts
import { createSlice } from "#reduxjs/toolkit";
interface BasketItem {
id: string;
title: string;
image: string;
description: string;
price: number;
category: string;
}
const initialState = {
items: [] as BasketItem[],
};
export const basketSlice = createSlice({
name: "basket",
initialState,
reducers: {
addToBasket: (state, action) => {
state.items = state.items.concat(action.payload);
},
removeFromBasket: (state, action) => {
const index = state.items.findIndex((basketItem: any) => basketItem.id === action.payload.id)
let newBasket = [...state.items];
if (index >= 0){
//if item exists in the basket remove it ...
newBasket.splice(index, 1);
} else {
console.warn(`cant remove (id: ${action.payload.id}) because its not in busket`)
}
state.items = newBasket;
},
},
});
export const { addToBasket, removeFromBasket } = basketSlice.actions;
// Selectors - This is how we pull information from the Global store slice
export const selectItems = (state: any) => state.basket.items;
export const selectTotal = (state: any) => state.busket.items.reduce((total:any, item:any) => total + item.price, 0);
const basketReducer = basketSlice.reducer;
export default basketReducer;
Cards.tsx
import Image from 'next/image';
import React, { useEffect, useState } from 'react';
import { StarIcon } from '#heroicons/react/solid';
// import Currency from 'react-currency-formatter';
import { useDispatch } from 'react-redux';
import { addToBasket } from "../basketSlice"
export default function Cards({id,title,image,description,price,category}: any) {
const dispatch = useDispatch()
const addItemsToBusket = () => {
const product = {
id,title,image,description,price,category
}
dispatch(addToBasket(product))//sending the product as an action to the redux store
}
const [rating, set] = useState(5);
const [hasPrime, setH] = useState(Math.random() < 1)
useEffect(() => {
set(Math.floor(Math.random() * 5) + 1 );
}, [])
useEffect(() => {
setH(Math.random() < 0.5 );
}, [])
return (
<div className="relative z-30 flex flex-col p-10 m-5 bg-white ">
<p className='absolute text-xs italic right-2 top-2'>{category}</p>
<Image className='mx-auto' src={image} height={200} width={200} alt=""/>
<h4 className='my-3'>{title}</h4>
<div className='flex'>
{Array(rating).fill(rating).map((_, i) => (
<StarIcon key={i} className='h-6 text-yellow-500'/>
))}
</div>
<p className='my-2 text-xs line-clamp-2 '>{description}</p>
<div>
{/* <Currency quantity={props.price} currency="INR"/> */}
<p className='mb-5'>₹{price}</p>
</div>
{hasPrime && (
<div className='flex items-center -mt-5 space-x-2'>
<img
className='w-12'
src="https://links.papareact.com/fdw" alt="" />
<p className='text-xs text-gray-500'>Free Next-Day Delivary</p>
</div>
)}
<button onClick={addItemsToBusket} className='mt-auto button'>Add to Busket</button>
</div>
)
}
ProductsFeed.tsx
import React from 'react'
import Cards from './Cards'
export default function({ products }: any) {
return (
<div className="grid grid-flow-row-dense mx-auto md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 md:-mt-40 lg:-mt-52">
{products.slice(0,4).map((product: any) => (
<Cards
key={product.id}
id={product.id}
title={product.title}
price={product.price * 60}
description={product.description}
category={product.category}
image={product.image}
/>
))}
<img className="md:col-span-full" src="https://links.papareact.com/dyz" alt="" />
<div className='md:col-span-2'>
{products.slice(4,5).map((product: any) => (
<Cards
key={product.id}
id={product.id}
title={product.title}
price={product.price * 60}
description={product.description}
category={product.category}
image={product.image}
/>
))}
</div>
{products.slice(5, products.length).map((product: any) => (
<Cards
key={product.id}
id={product.id}
title={product.title}
price={product.price * 60}
description={product.description}
category={product.category}
image={product.image}
/>
))}
</div>
)
}
checkout.tsx
import React from 'react'
import Nav from '../components/Nav'
import { signIn, signOut, useSession } from "next-auth/react"
import { useSelector } from 'react-redux';
import { selectItems } from '../basketSlice';
import CheckOutProduct from '../components/CheckOutProduct';
export default function CheckOut() {
const { data: session } = useSession()
const items = useSelector(selectItems);
console.warn(items)
return (
<div className='h-screen bg-gray-100'>
<Nav />
<main>
{!session? (
<div>
<div className='flex items-center justify-start p-10 m-10 space-x-4 overflow-hidden bg-white md:space-x-10'>
<img src="/checkout.svg" className='h-[7rem] w-[7rem] sm:w-[15rem] sm:h-[15rem]' alt=""/>
<div className=''>
<h1 className='font-bold md:text-[2rem] mb-1'>Your Amazon Cart is empty</h1>
<p className='text-[#007185] hover:text-red-600 cursor-pointer hover:underline hover'>Shop today's deals</p>
<button
className='px-10 py-2 mt-4 button'
onClick={() => signIn()}>Sign in to your account</button>
</div>
</div>
<div className=' h-[5rem] bg-white mx-10' />
</div>
): (
<div>
<div className='flex items-center justify-start p-10 m-10 space-x-4 overflow-hidden bg-white md:space-x-10'>
<img src="/checkout.svg" className='h-[7rem] w-[7rem] sm:w-[15rem] sm:h-[15rem]' alt=""/>
<div className=''>
<h1 className='font-bold md:text-[2rem] mb-1'>
{items.length === 0? "Your Amazon Cart is empty": "Shoping Basket"}
</h1>
<p className='text-[#007185] hover:text-red-600 cursor-pointer hover:underline hover'>Shop today's deals</p>
</div>
</div>
<div className='mx-10 bg-white '>
{items.length !== 0 && `You have ${items.length} items in your busket.`}
{items.map(({item, i}: any) => {
<CheckOutProduct
key={i}
image={item.image}
price={item.price}/>
})}
</div>
</div>
)}
</main>
</div>
)
}
checkOutProduct.tsx
import Image from 'next/image'
import React from 'react'
export default function CheckOutProduct({ id,title,image,description,price,category }: any) {
return (
<div className='grid grid-cols-5'>
<Image src={image} height={200} width={200} alt=""/>
<p>{price}</p>
</div>
)
}
Try to add like below because concat will not change object reference since updated values will not show in component.
addToBasket: (state, action) => {
state.items = [...state.items, ...action.payload];
}

getServerSideProps pass Undefined value

Sticker.ts
import React from "react";
import Image from "next/image";
import {GetServerSideProps, InferGetServerSidePropsType } from 'next';
import Product from "models/Product";
import currencyFormatter from "lib/currencyFormatter";
import mongoose from "mongoose";
import handler from "pages/api/pincode";
// const Sticker = (props: any) => {
const Sticker = ({products}) => {
// const products = JSON.parse((props?.products));
console.log("list of product "+ products)
return (
<div>
<section className="text-gray-600 body-font">
<div className="container px-5 py-24 mx-auto">
<div className="flex flex-wrap -m-4 justify-centr">
{/* {products?.map((dt: any, idx: number) => */}
{/* <div className="lg:w-1/4 md:w-1/2 p-4 w-full" key={idx}> */}
<div className="lg:w-1/4 md:w-1/2 p-4 w-full" >
{/* <a href={`./product/${dt?.category}/${dt?.id}`} className="block relative h-68 rounded overflow-hidden"> */}
<a href="./product/{category}/slug[jhbjh]" className="block relative h-68 rounded overflow-hidden">
<Image
alt="ecommerce"
className="object-cover cursor-pointer object-center w-full h-full block"
src="https://m.media-amazon.com/images/I/61SFAM62ucL._SL1280_.jpg"
width="100"
height="100"
/>
</a>
<div className="mt-4">
<h3 className="text-gray-500 text-xs tracking-widest title-font mb-1">
Home Decor
</h3>
<h2 className="text-gray-900 title-font text-lg font-medium">
Paper Plane Design Quote and Motivational Posters 12X18
</h2>
<p className="mt-1">{currencyFormatter(179)}</p>
</div>
</div>
{/* )} */}
</div>
</div>
</section>
</div>
);
};
export async function getServerSideProps(context) {
if(!mongoose.connections[0].readyState){
await mongoose.connect(process.env.MONGO_URI)
}
let products = await Product.find()
return {
// props: { products },
props: { products : JSON.parse(JSON.stringify(products)) },
}
}
export default Sticker;
_app.tsx
import React, { useEffect, useState } from 'react'
import { NextUIProvider, useSSR } from '#nextui-org/react';
import '../styles/globals.css'
import Navbar from '../modules/body/Navbar';
import Footer from '../modules/body/Footer';
import theme from "../themes";
import { AppProps } from 'next/app';
// import SideNavbar from '../mainComponent/SideNavbar'
function MyApp({ Component, pageProps }: AppProps) {
const [cart, setCart] = useState<object>({})
const [subTotal, setSubTotal] = useState<number>(0)
const { isBrowser } = useSSR();
useEffect(() => {
try {
if (localStorage.getItem("cart")) {
setCart(JSON.parse(localStorage.getItem("cart") || ""))
saveCart(JSON.parse(localStorage.getItem("cart") || ""))
}
} catch (error) {
console.log(error);
localStorage.clear()
}
}, [])
const saveCart = (myCart: object) => {
localStorage.setItem("cart", JSON.stringify(myCart))
// let keys = Object.keys(myCart);
const subt = Object.values(myCart).reduce((acc, curr) => acc + curr?.price * curr?.qty,0);
setSubTotal(subt)
}
const addToCart = (itemCode, qty, price, name, size, variant) => {
let newCart = cart;
if (itemCode in cart) {
newCart[itemCode].qty = cart[itemCode].qty + qty
}
else {
newCart[itemCode] = { qty: 1, price, name, size, variant }
}
setCart(newCart)
saveCart(newCart)
}
const removeFromCart = (itemCode, qty, price, name, size, variant) => {
let newCart = JSON.parse(JSON.stringify(cart));
if (itemCode in cart) {
newCart[itemCode].qty = cart[itemCode].qty - qty
}
if (newCart[itemCode]["qty"] <= 0) {
delete newCart[itemCode]
}
setCart(newCart)
saveCart(newCart)
}
const clearCart = () => {
setCart({})
saveCart({})
}
return isBrowser && (
<NextUIProvider theme={theme}>
<Navbar key={subTotal} cart={cart} addToCart={addToCart} removeFromCart={removeFromCart}
clearCart={clearCart} subTotal={subTotal} />
{/* <SideNavbar /> */}
<Component cart={cart} addToCart={addToCart} removeFromCart={removeFromCart}
clearCart={clearCart} subTotal={subTotal} {...pageProps} />
<Footer />
</NextUIProvider>
)
}
export default MyApp
I tried every method posted on the browser but still it shows undefined. If you help me to find out the solution of this problem then i will be very happy and feel blessed with this coding environment. please solve this as soon as possible. My whole project is stucked because of this error.

Failed prop type: Invalid prop `className` of type 'function'

I am making a Navbar for my dashboard but encountered this error which says I should pass a string to className and not function . I am passing the function to className as I have to check if the navbar is open or not. How can I solve this error?
Here is my code for navbar:
//STYLES
import styles from "./Navbar.module.scss";
import React from 'react';
//CONTEXT
import { useContext } from "react";
import NavContext from "../../context/NavContext";
//REACT ROUTER
import { NavLink } from "react-router-dom";
//ICONS
import {
MdOutlineDashboard,
MdOutlineAnalytics,
MdOutlinedFlag,
MdPeopleOutline,
MdOutlineMessage,
MdOutlineLogout,
} from "react-icons/md";
import { FaTimes } from "react-icons/fa";
import { BsThreeDots } from "react-icons/bs";
import { VscDashboard } from "react-icons/vsc";
const NavUrl = ({ url, icon, description }) => {
const { nav, setNav } = useContext(NavContext);
const checkWindowSize = () => {
if (window.innerWidth < 1024) setNav(!nav);
};
return (
<li className={styles.li_navlink}>
<NavLink
to={`${url}`}
className={({ isActive }) => (isActive ? styles.active : undefined)}
onClick={() => checkWindowSize()}
>
{icon}
<span className={styles.description}>{description}</span>
</NavLink>
</li>
);
};
const Navbar = () => {
const { nav, setNav } = useContext(NavContext);
return (
<div
className={`${styles.navbar_container} ${
nav ? styles.navbar_mobile_active : undefined
}`}
>
<nav className={nav ? undefined : styles.nav_small}>
{/* LOGO */}
<div className={styles.logo}>
<VscDashboard className={styles.logo_icon} />
<FaTimes
className={styles.mobile_cancel_icon}
onClick={() => {
setNav(!nav);
}}
/>
</div>
{/* MENU */}
<ul className={styles.menu_container}>
{/* FIRST CATEGORY */}
<span className={styles.categories}>
{nav ? "Pages" : <BsThreeDots />}
</span>
<NavUrl
url="/"
icon={<MdOutlineDashboard />}
description="Dashboard"
/>
<NavUrl
url="usage"
icon={<MdOutlineAnalytics />}
description="Usage"
/>
<NavUrl
url="plan"
icon={<MdOutlinedFlag />}
description="Plan"
/>
<NavUrl url="documentation" icon={<MdPeopleOutline />} description="Documentation" />
<NavUrl
url="invoices"
icon={<MdOutlineMessage />}
description="Invoices"
/>
</ul>
{/* LOGOUT BUTTON */}
<div
className={`${styles.btn_logout}`}
onClick={() => {
setNav(!nav);
}}
>
<MdOutlineLogout />
</div>
</nav>
<div
className={nav ? styles.mobile_nav_background_active : undefined}
onClick={() => {
setNav(!nav);
}}
></div>
</div>
);
};
export default Navbar;
Here is my error which is saying to pass string in navlink , navurl ,ul , nav , navbar , div , App , route , switch , router , browserRouter classes :
index.js:1 Warning: Failed prop type: Invalid prop `className` of type
`function` supplied to `NavLink`, expected `string`.
in NavLink (at Navbar.jsx:33)
in NavUrl (at Navbar.jsx:73)
in ul (at Navbar.jsx:67)
in nav (at Navbar.jsx:54)
in div (at Navbar.jsx:49)
in Navbar (at App.jsx:24)
in div (at App.jsx:21)
in App (at src/index.js:19)
in Route (at src/index.js:19)
in Switch (at src/index.js:18)
in Router (created by BrowserRouter)
in BrowserRouter (at src/index.js:17)
I think you do it in the last div you have
<div
className={nav ? styles.mobile_nav_background_active : undefined}
onClick={() => {
setNav(!nav);
}}
></div>
may be you must use onMouseEnter
onMouseEnter={() => {
setisActive (true);
}}
onMouseLeave={() => {
setisActive (false);
}}
className={isActive ? styles.active : undefined}

Why clientHeight or offsetHeight not available on ref element on toggled div in React component with useRef hook

I have a React component which show and hide some content.
Here is working example.
const Collapse = ({ children }: Props) => {
const [isOpen, setIsOpen] = useState(false);
const [height, setHeight] = useState<number | undefined>(0);
const toggledHeight = isOpen ? height : 0;
const myRef = useRef<HTMLDivElement>(null);
const toggle = () => setIsOpen(!isOpen);
useEffect(() => {
setHeight(myRef.current?.clientHeight);
}, [myRef]);
// useLayoutEffect(() => {
// setHeight(myRef.current?.clientHeight);
// }, []);
return (
<React.Fragment>
<div
ref={myRef}
className={`content ${isOpen ? "isOpen" : ""}`}
style={{ height: `${toggledHeight}px` }}
>
{children}
{console.log(height)}
{console.log(myRef)}
</div>
<button type="button" onClick={toggle}>
<span>Toggle content</span>
</button>
</React.Fragment>
);
};
export default Collapse;
I want to create a css height transition when showing and hiding the content.
Why is myRef.current?.offsetHeight or myRef.current?.clientHeight not available and always 0?
In the Style you are passing the dynamic height. I think it's not getting in the pixels. So you need to change from
style={{ height: ${height+"px"} }}
Looks like you are telling it from the first moment to be 0 :)
No need to look for exact height number, just animate max-height
I've managed to animate you code like this:
const Collapse = ({ children }: Props) => {
const [isOpen, setIsOpen] = useState(false);
const toggle = () => {
setIsOpen(!isOpen);
};
return (
<>
<div
style={{
maxHeight: isOpen ? '1000px' : '0px',
transition: 'max-height 1s ease-in-out',
}}
>
{children}
</div>
<button type="button" onClick={toggle}>
<span>Toggle content</span>
</button>
</>
);
};

Table in react bootstrap. How can i make it fit inside a container?

I am using react bootstrap table to show my data. The table is not responsive and has a over-proportioned size on the right side.
Look also at the picture showing that the table is much larger than the other components.
I have tried to include a few css elements such as container, width, max-width, among others however nothing worked.
I am importing the Bootstrap CSS using this: import 'bootstrap/dist/css/bootstrap.min.css';
Thanks in advance.
index.jsx
import React from 'react'
import '../../../../src/styles.css'
export default function Datatable({ data }) {
const columns = data[0] && Object.keys(data[0]);
return (
<table class="table" >
<thead class=" table-striped table-bordered table-sm ">
<tr >{data[0] && columns.map((heading) => <th>{heading}</th>)}</tr>
</thead>
<tbody class=" table-striped table-bordered table-sm " >
{data.map((row) => (
<tr>
{ columns.map((column) => (
<td>{row[column]}</td>
))}
</tr>
))}
</tbody>
</table>
);
}
styles.css
body {
background: #fafafa;
}
table {
background: #f89c9c;
font-size: 14px;
text-align: center;
}
thead {
font-size: 20px;
}
Base.js
import React from 'react';
import Menu from "./Menu"
import Button from "react-bootstrap/Button";
import Container from "react-bootstrap/container";
import Row from "react-bootstrap/row";
const Base = ({
title = "My Title",
description = "My description",
className = "",
children
}) => {
return (
<div>
<Menu />
<Container fluid className="bg-light" >
<Container fluid >
<div className="col bg-light text-dark text-left pt-5" >
<Row >
<h2 className="col-9 display-4 ml-0 font-weight-bold">{title}</h2>
<Button variant="link" className=" btn bg-light text-dark font-weight-bold">Investor</Button>
<Button variant="link" className="btn bg-light text-dark font-weight-bold">Borrower</Button>
<Button variant="link" className=" btn bg-light text-dark font-weight-bold">Charity</Button>
</Row>
<p className=" lead ml-0 font-weight-bold">{description}</p>
</div>
</Container>
<div className={className}>{children}</div>
</Container >
<footer className="footer bg-dark mt-auto py-3">
UserDashboard.js
import React, {useState, useEffect} from 'react';
import Base from '../core/Base'
import './helper/EnhancedTable';
import { Dash } from './helper/EnhancedTable'
const UserDashboard = () => {
return (
<Base title="User dashboard">
<Dash ></Dash>
</Base>
)
}
export default UserDashboard;
Table.js
import {API} from "../../backend"
import React, {useState, useEffect} from 'react';
import Datatable from './datatable';
require("es6-promise").polyfill();
require("isomorphic-fetch");
export default function Dash() {
const [data, setData] = useState([]);
//now we create the quesry state
const [q, setQ] = useState("");
const [searchColumns, setSearchColumns] = useState(["description", "borrower_name"]);
//this is the function that we want tpo fire when the dependencies are triggered
useEffect(() => {
//fetch will make the call to the server
fetch(`${API}project/`, {method: "GET"})
//then response will handle answer from server transforming the HTTP data into JSON data
.then((response) => response.json())
//now that we access to the JSON data from server we will get if from the local storage
.then((json) => setData(json))
}, []);
function search(rows) {
return rows.filter(
(row ) =>
searchColumns.some(column => row[column].toString().toLowerCase().indexOf(q.toLowerCase()) > -1
)
);
}
const columns = data[0] && Object.keys(data[0])
return (
<div>
<input type="text" value={q} onChange={(e) => setQ(e.target.value) }/>
{
columns && columns.map(column =>
<label>
<input
type="checkbox"
checked={searchColumns.includes(column)}
onChange={(e) => {
const checked = searchColumns.includes(column);
setSearchColumns((prev) => checked
? prev.filter((sc) => sc !== column)
: [...prev, column]
);
}}
/>
{column}
</label>)
}
<Datatable data={search(data)} />
</div>
)
}
export {Dash};

Resources