I am trying to make a blog using ReactJS and NextJS in VS Code I don't have any error but when I run it it shows in browser: " TypeError: Cannot read properties of undefined (reading 'map') "
So this is the code
import React, { useState, useEffect } from 'react';
import Image from 'next/image';
import moment from 'moment';
import Link from 'next/link';
import { getSimilarPosts, getRecentPosts } from '../services';
const PostWidget = ({ categories, slug }) => {
const [relatedPosts, setRelatedPosts] = useState([]);
useEffect(() => {
if (slug) {
getSimilarPosts(categories, slug).then((result) => {
setRelatedPosts(result);
});
} else {
getRecentPosts().then((result) => {
setRelatedPosts(result);
});
}
}, [slug])
console.log(relatedPosts)
return (
<div className="bg-white shadow-lg rounded-lg p-8 pb-12 mb-8">
<h3 className="text-xl mb-8 font-semibold border-b pb-4">{slug ? 'Related Posts' : 'Recent Posts'}</h3>
{relatedPosts.map((post) => (
<div key={post.title} className="flex items-center w-full mb-4">
<div className="w-16 flex-none">
<img
alt={post.title}
height="60px"
width="60px"
unoptimized
className="align-middle rounded-full"
src={post.featuredImage.url}
/>
</div>
<div className="flex-grow ml-4">
<p className="text-gray-500 font-xs">{moment(post.createdAt).format('MMM DD, YYYY')}</p>
<Link href={`/post/${post.slug}`} className="text-md" key={index}>{post.title}</Link>
</div>
</div>
))}
</div>
);
};
export default PostWidget;
And this is where the error is.
{relatedPosts.map((post) =>
use ? make in this code:
{relatedPosts?.map((post) =>
Check relatedPosts has data before rendering map.
If not working please share getSimilarPosts, getRecentPosts
{
relatedPosts &&
relatedPosts.length > 0 &&
relatedPosts.map((post) => (
...
))
}
Related
Here is my React component. The hook I am trying to get to work is useGetNotesQuery.
On initial load of the component, it does not run. If I tab switch, or create a new note, then the hook will be called and the component will update. I don't have this problem with other hooks and I can't seem to figure out what I am doing wrong. I'm still pretty new to react-query. I've verified that when the hook is called on tab switch or the creation of a new note, the correct data is being passed in and the hook works as expected. It just will not run on initial load.
import React, { useState } from 'react';
import useGetNotesQuery from 'hooks/notes/useNotes';
import { useCreateNote } from 'hooks/notes/useCreateNote';
import Note from './Note';
export default function Notes({ projectItemId, itemId, itemType }: any) {
const createNote = useCreateNote();
const {
data: notes,
isLoading,
isError
} = useGetNotesQuery({ projectItemId, itemId, itemType });
const [body, setBody] = useState('');
const createNewNote = async () => {
await createNote.mutateAsync({
body,
projectItemId,
itemId,
itemType
});
setBody('');
};
return (
<section aria-labelledby="notes-title">
{!isLoading && (
<div className="sm:overflow-hidden sm:rounded-lg">
{console.log(notes)}
<div className="divide-y divide-gray-200">
<div className="px-4 py-5 sm:px-6">
<h2
id="notes-title"
className="text-lg font-medium text-gray-900"
>
Notes
</h2>
</div>
<div className="px-4 py-6 sm:px-6">
<ul role="list" className="space-y-8">
{notes?.map((note) => (
<Note key={note.id} note={note} />
))}
</ul>
</div>
</div>
<div className="bg-gray-50 px-4 py-6 sm:px-6">
<div className="flex space-x-3">
{/* <div className="flex-shrink-0">
<img
className="h-10 w-10 rounded-full"
src={user.imageUrl}
alt=""
/>
</div> */}
<div className="min-w-0 flex-1">
<form action="#">
<div>
<label htmlFor="comment" className="sr-only">
About
</label>
<textarea
id="comment"
name="comment"
rows={3}
className="block w-full p-2 rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 sm:text-sm text-black"
placeholder="Add a note"
value={body}
onChange={(e) => setBody(e.target.value)}
/>
</div>
<div className="mt-3">
<button
type="submit"
onClick={(e) => {
e.preventDefault();
createNewNote();
}}
className="inline-flex items-center justify-center rounded-md border border-transparent bg-blue-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2"
>
Comment
</button>
</div>
</form>
</div>
</div>
</div>
</div>
)}
</section>
);
}
Here is the hook
import { getNotesById } from './../../queries/notes/get-notes';
import { useQuery } from 'react-query';
function useGetNotesQuery({ projectItemId, itemId, itemType }: any) {
return useQuery('notes', async () => {
if (projectItemId) {
return getNotesById({ projectItemId, itemId, itemType }).then(
(result) => result.data
);
}
});
}
export default useGetNotesQuery;
My _app.tsx file in NextJS
import 'styles/main.css';
import 'styles/chrome-bug.css';
import '#/styles/tailwind.css';
import 'katex/dist/katex.css';
import '../styles/globals.css';
import 'react-datepicker/dist/react-datepicker.css';
import { useEffect, useState } from 'react';
import React from 'react';
import { SessionContextProvider } from '#supabase/auth-helpers-react';
import { createBrowserSupabaseClient } from '#supabase/auth-helpers-nextjs';
import { AppProps } from 'next/app';
import { MyUserContextProvider } from 'utils/useUser';
import type { Database } from 'types_db';
import { SidebarProvider } from 'context/SidebarContext';
import { QueryClient, QueryClientProvider } from 'react-query';
// import { ReactQueryDevtools } from 'react-query/devtools';
import { ThemeProvider } from 'next-themes';
const queryClient = new QueryClient({
defaultOptions: {
queries: {
retry: 3
}
}
});
export default function MyApp({ Component, pageProps }: AppProps) {
const [initialContext, setInitialContext] = useState();
const [supabaseClient] = useState(() =>
createBrowserSupabaseClient<Database>()
);
useEffect(() => {
document.body.classList?.remove('loading');
}, []);
return (
<QueryClientProvider client={queryClient}>
<SessionContextProvider supabaseClient={supabaseClient}>
<MyUserContextProvider initial={initialContext}>
<SidebarProvider>
<ThemeProvider
attribute="class"
enableColorScheme={false}
defaultTheme="light"
>
<Component {...pageProps} />
</ThemeProvider>
{/* <ReactQueryDevtools initialIsOpen={false} /> */}
</SidebarProvider>
</MyUserContextProvider>
</SessionContextProvider>
</QueryClientProvider>
);
}
What do your other hooke return? Your query getNotesById is returning result.data, but the useQuery structure expects a parsed result object, like the example below:
const fetchUsers = async () => {
const res = await fetch("https://jsonplaceholder.typicode.com/users");
return res.json();
};
const response = useQuery("users", fetchUsers);
I am using #react-oauth/google package.
Login.js
import React from 'react';
import { GoogleOAuthProvider } from '#react-oauth/google';import { useNavigate } from 'react-router-dom';
import shareVideo from '../assets/share.mp4';
import logo from '../assets/logowhite.png';
import { GoogleLogin } from '#react-oauth/google';
import { client } from '../client';
const Login = () => {
const navigate = useNavigate();
const responseGoogle=(response) => {
localStorage.setItem('user', JSON.stringify(response.profileObj))
const {name, googleId, imageUrl} = response.profileObj;
const doc = {
_id: googleId,
_type: 'user',
image: imageUrl,
userName: name,
}
client.createIfNotExists(doc)
.then(() =>{
navigate('/', {replace:true})
})
}
return (
<div className='flex justify-start items-center flex-col h-screen'>
<div className='relative w-full h-full'>
<video src={shareVideo}
type="video/mp4"
loop
muted
autoPlay
className='w-full h-full object-cover'
/>
<div className='absolute flex flex-col justify-center items-center top-0 right-0 left-0 bottom-0 bg-blackOverlay'>
<div className='p-5'>
<img src={logo} width="130px" alt="logo" />
</div>
<div className='shadow-2x1'>
<GoogleOAuthProvider
clientId={process.env.REACT_APP_GOOGLE_API_TOKEN}
>
<GoogleLogin
onSuccess= {responseGoogle}
onError={() => {
console.log('Login Failed');
}}
cookiePolicy="single_host_origin"
/>;
</GoogleOAuthProvider>
</div>
</div>
</div>
</div>
);
}
export default Login;
I got console error:-Cannot destructure property 'name' of 'response.profileObj' as it is undefined.
I want to route to homepage but its not working.
i tried to use gapi
import React from 'react';
import { GoogleOAuthProvider } from '#react-oauth/google';import { useNavigate } from 'react-router-dom';
import shareVideo from '../assets/share.mp4';
import logo from '../assets/logowhite.png';
import { GoogleLogin } from '#react-oauth/google';
import { client } from '../client';
import { gapi } from "gapi-script";
const Login = () => {
const navigate = useNavigate();
const clientId={process.env.REACT_APP_GOOGLE_API_TOKEN}
const initClient = () => {
gapi.client.init({
clientId: clientId,
scope: "",
});
};
gapi.load("client:auth2", initClient);
const responseGoogle=(response) => {
localStorage.setItem('user', JSON.stringify(response.profileObj))
const {name, googleId, imageUrl} = response.profileObj;
const doc = {
_id: googleId,
_type: 'user',
image: imageUrl,
userName: name,
}
client.createIfNotExists(doc)
.then(() =>{
navigate('/', {replace:true})
})
}
return (
<div className='flex justify-start items-center flex-col h-screen'>
<div className='relative w-full h-full'>
<video src={shareVideo}
type="video/mp4"
loop
muted
autoPlay
className='w-full h-full object-cover'
/>
<div className='absolute flex flex-col justify-center items-center top-0 right-0 left-0 bottom-0 bg-blackOverlay'>
<div className='p-5'>
<img src={logo} width="130px" alt="logo" />
</div>
<div className='shadow-2x1'>
<GoogleOAuthProvider
clientId={process.env.REACT_APP_GOOGLE_API_TOKEN}
>
<GoogleLogin
onSuccess= {responseGoogle}
onError={() => {
console.log('Login Failed');
}}
/>;
</GoogleOAuthProvider>
</div>
</div>
</div>
</div>
);
}
export default Login;
got console error Forced reflow while executing JavaScript.
I don't know how to solve this problem.
I am loading data from firebase, so when I refresh, it takes time to load it. And added data are not present in the cart that,s why I am not getting any product in the cart. But I did follow the same process to store user data, and it,s working fine, which means I am getting a registered profile in console. Can anyone suggest me a solution for getting data in the cart?
sending data:
import { motion } from "framer-motion";
import React, { useEffect, useRef, useState } from "react";
import { MdShoppingBasket } from "react-icons/md";
import { actionType } from "../context/reducer";
import { useGlobalState } from "../context/stateProvider";
import NotFound from "../img/NotFound.svg";
const RowContainer = ({ flag, data, scrollValue }) => {
const [{ cartItems }, dispatch] = useGlobalState();
const [items, setItems] = useState([]);
const rowContainer = useRef();
const addToCart = () => {
dispatch({
type: actionType.SET_CARTITEMS,
cartItems: items,
});
localStorage.setItem("cartItems", JSON.stringify(items));
};
useEffect(() => {
addToCart();
}, [items]);
useEffect(() => {
rowContainer.current.scrollLeft += scrollValue;
}, [scrollValue]);
return (
<div
ref={rowContainer}
className={`w-full my-12 flex items-center ${
flag
? "overflow-x-scroll scrollbar-none scroll-smooth"
: "overflow-x-hidden flex-wrap justify-center"
}`}
>
{data && data.length > 0 ? (
data.map((item) => {
const { id, price, imageURL, calories, title } = item;
return (
<div
key={id}
className="w-350 min-w-[300px] md:min-w-[380px] md:my-10 backdrop-blur-lg mx-1 my-2 lg:mx-2 "
>
<div className="w-full flex flex-row items-center justify-between bg-white rounded-lg drop-shadow-lg py-2 px-4 hover:bg-whiteAlpha min-h-[150px]">
<motion.img
whileHover={{ scale: 1.2 }}
src={imageURL}
alt="img"
className="w-30 max-h-40 -mt-8 duration-100 drop-shadow-2xl"
/>
<div className="flex flex-col items-end justify-end gap-4">
<motion.div
whileTap={{ scale: 0.75 }}
className="w-8 h-8 rounded-md bg-orange-500 hover:bg-orange-600 "
onClick={() => setItems([...new Set(cartItems), item])}
>
<MdShoppingBasket className="text-white text-2xl m-1" />
</motion.div>
<div className=" w-full">
<p className="text-gray-800 md:text-lg text-base text-right">
{title}
</p>
<p className="text-sm text-gray-500 text-right">
<span className="text-orange-600">$</span> {price}
</p>
</div>
</div>
</div>
</div>
);
})
) : (
<div className="w-full flex flex-col items-center justify-center">
<img src={NotFound} className="h-340" alt="" />
<p className="text-center my-2 text-xl text-red-500">No data found</p>
</div>
)}
</div>
);
};
export default RowContainer;
fetching data
export const fetchCart = () => {
const cartInfo =
localStorage.getItem("cartItems") !== "undefined"
? JSON.parse(localStorage.getItem("cartItems"))
: localStorage.clear();
return cartInfo ? cartInfo : [];
};
You are clearing your data for no reason
localStorage.getItem("cartItems") !== "undefined"
should be
localStorage.getItem("cartItems") !== undefined
In this file, I got this error. `Unhandled Runtime Error
TypeError: messages is undefined` (I'm building and NEXT app)
Please help me to solve this error. messages will be loaded with postman, Problem with this page. The query I have been checked with postman and data fetched succesfully
import React, { useEffect, useState } from 'react';
import { HiPlusSm } from 'react-icons/hi';
import router from 'next/router';
import Link from 'next/link';
import axios from 'axios';
const MessageList = () => {
const [messages, setMessages] = useState([]);
//TODO check how to get the current user id - localstorage.getitem()
useEffect(() => {
const fetchMessages = async () => {
await axios
.get('/api/messages/getMessages', {
params: { sender: '62de47ab819e077df87d0661' },
})
.then((result) => {
setTimeout(() => setMessages(result.data.messages), 1000);
})
.then((result) => {
if (!result.data.messages) {
return null;
}
})
.catch((err) => {
console.log(err);
});
};
fetchMessages();
}, []);
return (
<div className={'bg-gray-100'}>
<div className="mx-auto py-4 px-4 pt-8 md:max-w-4xl">
<div className={'w-full bg-white p-5 shadow-sm'}>
<div className="mt-4 px-1">
<Link href="/inbox/new">
<button
className={`inline-flex items-center rounded-md border border-transparent bg-red-100 px-4 py-1.5 text-xs font-medium text-susty shadow-sm hover:border-susty hover:bg-susty hover:text-white`}
>
<HiPlusSm className="mr-2 h-5 w-5 items-center" />
New Message
</button>
</Link>
</div>
<div className="w-full overflow-auto bg-white shadow md:h-[410px] xl:h-[630px]">
<div className="h-full w-full">
<div className={'mt-10 flex flex-col-reverse'}>
{messages.map((msg) => (
<div key={msg} id={msg}>
<span>{msg.message}</span>
</div>
))}
</div>
</div>
</div>
</div>
</div>
</div>
);
};
export default MessageList;
I am using Nextjs and there is a sidebar in which I am trying to get random 5 posts from an array of objects. The defined function is working fine and displaying 5 posts but I am getting a Hydration error showing Prop alt did not match. When I tried to display it on the console the alt value is different.
import Link from 'next/link';
import Image from 'next/image';
import { BlogData } from '../data/blogdata';
function getMultipleRandom() {
const shuffled = [...BlogData].sort(() => 0.5 - Math.random());
return shuffled.slice(0, 5);
}
const Sidebar = () => {
return (
<>
<h2 className='font-roboto text-3xl font-semibold pb-10'>Featured Posts</h2>
{
getMultipleRandom().map((val) => {
return (
<div key={val._id} className='flex flex-col pt-5'>
<div className='w-56 pr-5'><Image src={val.featuredImage} alt={val.alt} width={1200} height={800} className=' rounded-3xl' /></div>
<Link href={`/blog/${val.slug}`}><a><h3 className='text-sm font-poppins font-medium hover:text-[#5836ed] transition-all duration-300'>{val.title}</h3></a></Link>
</div>
);
})
}
</>
)
}
export default Sidebar;
try this code :
import Link from "next/link";
import Image from "next/image";
import { BlogData } from "../data/blogdata";
import { useEffect, useState } from "react";
const Sidebar = () => {
const [shuffled, setShuffled] = useState([]);
const [loading, setLoading] = useState(true); // anyting you want !!!
useEffect(() => {
if (loading) {
const x = [...BlogData].sort(() => 0.5 - Math.random());
setShuffled(x.slice(0, 5));
setLoading(false);
}
}, [loading]);
return (
<>
<h2 className="font-roboto text-3xl font-semibold pb-10">
Featured Posts
</h2>
{loading ? <div>loading ... </div> : shuffled.map((val) => {
return (
<div key={val._id} className="flex flex-col pt-5">
<div className="w-56 pr-5">
<Image
src={val.featuredImage}
alt={val.alt}
width={1200}
height={800}
className=" rounded-3xl"
/>
</div>
<Link href={`/blog/${val.slug}`}>
<a>
<h3 className="text-sm font-poppins font-medium hover:text-[#5836ed] transition-all duration-300">
{val.title}
</h3>
</a>
</Link>
</div>
);
})}
</>
);
};
export default Sidebar;