I started implementing the React-simple-lightbox. It all works fine on the chosen images, but I do have another problem. I get an error on some of my articles that have an image and a title. It gives me the following error:
What's possibly the issue here?
Unhandled Runtime Error
TypeError: Cannot read properties of null (reading 'nodeName')
Call Stack
eval
node_modules/simple-react-lightbox/dist/index.es.js (14:71687)
eval
node_modules/simple-react-lightbox/dist/index.es.js (14:72063)
Array.forEach
<anonymous>
eval
node_modules/simple-react-lightbox/dist/index.es.js (14:71638)
eval
node_modules/simple-react-lightbox/dist/index.es.js (14:73845)
const PlockGrid = ({title, photoConst, photoSrc} : Props) => {
return (
<SRLWrapper options={options}>
<Plock breakpoints={breakpoints} gap="2rem">
{
[...Array(photoCount[photoConst])].map((e, i) => {
return <img
key={i + 1}
src={`${photoSrc}${i + 1}.webp`}
alt={`${title} detail`}
className="bg-gray-200 w-full hover:grayscale cursor-pointer"
loading="lazy"
/>
})
}
</Plock>
</SRLWrapper>
)
}
import { AppProps } from 'next/app'
import '../styles/index.css'
import SimpleReactLightbox from 'simple-react-lightbox'
export default function MyApp({ Component, pageProps }: AppProps) {
return <SimpleReactLightbox><Component {...pageProps} /></SimpleReactLightbox>
}
Here's the affected file with the articles as well:
import PostPreview from './post-preview'
import type Post from '../interfaces/post'
import FramerMotion from './framer-motion'
type Props = {
posts: Post[]
}
const MoreStories = ({ posts }: Props) => {
return (
<section>
<FramerMotion>
<h2 className="mb-8 text-5xl md:text-7xl font-bold tracking-tighter leading-tight">
My work
</h2>
</FramerMotion>
<div className="grid grid-cols-1 md:grid-cols-2 md:gap-x-8 xl:grid-cols-3 xl:gap-x-12 gap-y-20 mb-32">
{posts.map((post) => (
<PostPreview
key={post.slug}
title={post.title}
coverImage={post.coverImage}
date={post.date}
slug={post.slug}
/>
))}
</div>
</section>
)
}
export default MoreStories
Related
Hey I am learning reactjs as much as i have learned I am trying to make note app
my code given below
my App.js file
import React , {useEffect, useState} from "react"
import { nanoid } from "nanoid"
import Editor from './Note/Editor'
import Sidebar from "./Note/Sidebar"
function App() {
const [notes , setNotes] = useState(JSON.parse(localStorage.getItem("notes"))||[])
const [currentNoteID , setCurrentNoteID] = useState(false)
useEffect(()=>{
localStorage.setItem("notes" , JSON.stringify(notes))
},[notes])
function createNewNotes(){
const newNotes = {
id: nanoid(),
title:"untitled",
body: "sdasda",
lastModified: Date.now()
}
setNotes(prevNote => [newNotes , ...prevNote])
setCurrentNoteID(newNotes.id)
}
function deleteNote(noteID){
setNotes(prevNote => prevNote.filter(note=> note.id !== noteID ))
}
function getNotes(){
return notes.find((note)=> note.id === currentNoteID)
}
return (
<div className="note">
<Sidebar
notes={notes}
createNewNotes={createNewNotes}
currentNoteID={currentNoteID}
setCurrentNoteID={setCurrentNoteID}
deleteNote={deleteNote}
/>
<Editor
notes={getNotes()}
currentNoteID={currentNoteID}/>
</div>
);
}
export default App;
my Sidebar.js file
import React from 'react'
import './style.css'
export default function Sidebar(props){
return(
<>
<div className='sidebar' >
<div className='sidebar-header'>
<h3>Notes</h3>
<button className='add' onClick={props.createNewNotes} >Add</button>
</div>
{ props.notes.map((note)=>{
return(
<div key={note.id}
className={`${note.id===props.currentNoteID ? "active" : ""}`}
onClick={()=>props.setCurrentNoteID(note.id)}
>
<div>
<div className="sidebar-tab">
<div className='sidebar-title'>
<p className='title'>Untitled</p>
<button className='delete' onClick={()=>props.deleteNote(note.id)}>Delete</button>
</div>
<p className='note-preview'>summary of text</p>
</div>
</div>
</div>
)
})}
</div>
</>
)
}
my Editor.js file
import React , {useState} from "react";
import './style.css'
export default function Editor(props){
const [edit , setEdit] = useState(props.notes)
function handleChange(event){
const {name , value} = event.target
setEdit(prevNote=> {
return {
...prevNote,
[name] : value
}
})
}
if(!props.currentNoteID)
return <div className="no-note">no note active</div>
return(
<>
<div className="main">
<input type="text" className="main-input" name="title" placeholder="Enter title here" value={edit.title} onChange={handleChange} autoFocus/>
<textarea className="main-textarea" name="body" placeholder="Type your notes" value={edit.body} onChange={handleChange} />
<div className="preview">
<h1 className="preview-title">{edit.title}</h1>
<div className="main-preview">{edit.body}</div>
</div>
</div>
</>
)
}
whenever i click add button or any sidebar button it shows me error
Uncaught TypeError: Cannot read properties of undefined (reading 'title')
please help me out how to fix this issue
You're expecting getNotes (which should probably be named getActiveNote, IMHO) to re-run every time notes or currentNoteID change.
To achieve this, you have to declare it as a callback (useCallback) and to declare its dependencies. Also you want to place the result in state (e.g: activeNote):
const getActiveNote = useCallback(
() => notes.find((note) => note.id === currentNoteID),
[notes, currentNoteID]
);
const [activeNote, setActiveNote] = useState(getActiveNote());
useEffect(() => {
setActiveNote(getActiveNote());
}, [getActiveNote]);
// ...
<Editor note={activeNote} />
... at which point, you no longer need the currentNoteID in the <Editor /> as you can get it from props.note.id.
See it working here: https://codesandbox.io/s/crazy-glade-qb94qe?file=/src/App.js:1389-1448
Note: the same thing needs to happen in <Editor>, when note changes:
useEffect(() => setEdit(note), [note]);
I keep having errors trying to deploy my Nextjs app to vercel:
Error occurred prerendering page "/". Read more: https://nextjs.org/docs/messages/prerender-error
TypeError: (0 , react_development_.useState) is not a function or its return value is not iterable
at Categories (/vercel/path0/.next/server/chunks/930.js:122:72)
at d (/vercel/path0/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:33:498)
at bb (/vercel/path0/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:36:16)
at a.b.render (/vercel/path0/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:42:43)
at a.b.read (/vercel/path0/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:41:83)
at Object.exports.renderToString (/vercel/path0/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:52:138)
at Object.renderPage (/vercel/path0/node_modules/next/dist/server/render.js:686:46)
at Object.defaultGetInitialProps (/vercel/path0/node_modules/next/dist/server/render.js:316:51)
at Function.getInitialProps (/vercel/path0/.next/server/pages/_document.js:514:20)
at Object.loadGetInitialProps (/vercel/path0/node_modules/next/dist/shared/lib/utils.js:69:29)
I tried npm run build locally and I get this error:
> Build error occurred
Error: Export encountered errors on following paths:
/
/post/[slug]: /post/first-post
/post/[slug]: /post/how-html-css-js-work
/post/[slug]: /post/nextjs
/post/[slug]: /post/react-hooks
So I assume it has to be something inside my index page and /post/[slug] page. I tried everything like setting getStaticPaths fallback to false and using optional chaining everywhere but I still get the error.
Can someome please help me out, it is so depressing when I finished the project and I can run it in my localhost but and failed in the deployment/build time.
My / page:
import Head from "next/head";
import { PostCard, Categories, PostWidget } from "../components";
import { getPosts } from "../services";
export default function Home({ posts }) {
const sortedPosts = posts.sort(
(a, b) => new Date(b.node.createdAt) - new Date(a.node.createdAt)
);
return (
<>
<Head>
<title>JBLOG | Home</title>
</Head>
<section className="bg-zinc-200 dark:bg-gray-500 transition-colors px-5">
<div className="max-w-7xl mx-auto py-10">
<div className="grid grid-cols-1 md:grid-cols-12 gap-12">
<div className="md:col-span-8 col-span-1 ">
{sortedPosts?.map((post) => (
<PostCard key={post.node.title} post={post.node} />
))}
</div>
<div className="md:col-span-4 col-span-1">
<div className="md:sticky relative md:top-[110px]">
<PostWidget />
<Categories />
</div>
</div>
</div>
</div>
</section>
</>
);
}
export async function getStaticProps() {
const posts = (await getPosts()) || [];
return {
props: {
posts,
},
};
}
My /post/slug page:
import React from "react";
import Head from "next/head";
import { getPosts, getPostDetails } from "../../services";
import {
PostDetail,
Categories,
PostWidget,
Author,
Comments,
CommentsForm,
} from "../../components";
import { useRouter } from "next/router";
const Post = ({ post }) => {
const router = useRouter();
if (router.isFallback) {
return <div>Loading...</div>;
}
return (
<>
<Head>
<title>{post?.title}</title>
</Head>
<section className="bg-zinc-200 dark:bg-gray-500 transition-colors px-5">
<div className="max-w-7xl mx-auto py-10">
<div className="grid grid-cols-1 md:grid-cols-12 md:gap-6">
<div className="md:col-span-8 col-span-1 ">
<PostDetail post={post} />
<CommentsForm slug={post?.slug} />
<Comments slug={post?.slug} />
</div>
<div className="md:col-span-4 col-span-1">
<div className="md:sticky relative md:top-[110px]">
<Author author={post?.author} />
<PostWidget
slug={post?.slug}
categories={post?.categories?.map(
(category) => category.slug
)}
/>
<Categories />
</div>
</div>
</div>
</div>
</section>
</>
);
};
export default Post;
export const getStaticProps = async (context) => {
const data = await getPostDetails(context.params.slug);
return {
props: {
post: data,
},
};
};
export const getStaticPaths = async () => {
const posts = await getPosts();
return {
paths: posts.map((post) => ({ params: { slug: post.node.slug } })),
fallback: true,
};
};
what's your npm run build?
https://nextjs.org/docs/basic-features/data-fetching
fallback: true is not supported when using next export.
As will be shown below when passing properties from a parent component to a child component my code is executed first before the properties arrive and when trying to do a .map of an Array it returns the error "Cannot read properties of undefined (reading 'map')". Why does this happen?
As you can see in the image, first you get undefined values which generates the error in the .map and then you get the properties
Parent component:
import React, {useEffect, useState} from "react";
import ItemDetail from "./itemDetail";
import '../../App.css';
import { useParams } from "react-router-dom";
//Component Class
const ItemDetailContainer = () => {
const [producto, productos] = useState([]);
const { productId } = useParams();
useEffect(() => {
fetch('http://localhost:3000/productos/' + productId)
.then(res=>res.json())
.then(data=>productos(data))
}, [productId]);
console.log(producto);
return (
<div className="container">
<ItemDetail
nombre={producto.nombre}
id={producto.id}
precio={producto.precio}
category={producto.category}
imagenes={producto.imagenes}
ancho={producto.ancho}
alto={producto.alto} />
</div>
)
}
export default ItemDetailContainer;
Child component:
import React from 'react';
import { Card } from 'react-bootstrap';
import ItemCount from '../itemCount';
const ItemDetail = ({ nombre, id, precio, category, imagenes, ancho, alto }) => {
console.log(imagenes);
return (
<div className="row" key={id} id={id}>
<div className="col-md-6" id="productImage">
<div className="carousel-item">
{imagenes.map((p) => (
<img src={p} className="d-block w-100" alt={nombre} />
))}
</div>
</div>
<div className="col-md-6 producto">
<div className="card">
<Card.Body>
<Card.Title>{nombre}</Card.Title>
<Card.Text>{category}</Card.Text>
<Card.Text>${precio}</Card.Text>
<ItemCount />
</Card.Body>
</div>
</div>
</div>
);
};
export default ItemDetail;
Change your code to only execute if imagenes is an array. Personally I would rethink how you are structuring your initial state. Instead of it being an empty array, perhaps make it an object with all of those properties having default values.
<div className="carousel-item">
{ Array.isArray(imagenes) && imagenes.map((p) => (
<img src={p} className="d-block w-100" alt={nombre} />
))}
</div>
I dont know why i have this error!!
At first time i dont have any error and its work But when i refresh the page i have this error:
TypeError: Cannot read property 'title' of undefined or TypeError: Cannot read property 'image' of undefined
import React, { useEffect , useState } from 'react';
import Content from './Content';
import NavBar from './NavBar';
export default function BlogPost() {
const [post, setPost] = useState([]);
const [current, setCurrent] = useState(null)
useEffect(() => {
const cleanUp = fetch('http://localhost:3000/posts')
.then( response => response.json())
.then( post =>
setPost(post),
setCurrent(0)
)
return () => cleanUp;
},[])
function handleClick(index) {
setCurrent(index)
}
return (
<div className="wrapper d-flex align-items-stretch">
<NavBar posts={post} handleClick={handleClick} />
{ null != current && <Content post={post[current]} />}
</div>
)
}
Content.jsx :
export default function Content({post}) {
return (
<div>
<div id="content" className="p-4 p-md-5 pt-5">
<img src={`/assets/${post.image}`} alt={post.title} />
<h2 className="mb-4">{post.title}</h2>
<p>{post.body}</p>
</div>
</div>
)
}
The issue is here:
<h2 className="mb-4">{post.title}</h2>
here post object will get data from axios call and it will take some time to fetch the data that means on initial render title will not be there. So you have to put some check and access that key only when it is available.
Try something like:
<h2 className="mb-4">{post && post.title}</h2>
Or you can also try conditional rendering
you could do the below instead:
export default function Content({post}) {
return post ? (
<div>
<div id="content" className="p-4 p-md-5 pt-5">
<img src={`/assets/${post.image}`} alt={post.title} />
<h2 className="mb-4">{post.title}</h2>
<p>{post.body}</p>
</div>
</div>
) : null
}
I am getting the following error after a refresh and sometimes on initial project run:
TypeError: Cannot read property 'statements' of undefined
This is really confusing because the data is rendering fine it just seems the connection fails. Any idea what may be causing the error?
There are no additional errors when I remove the statements.map
I used this medium article to get everything up and running: Medium Article
index.js:
import React, { useState, useReducer } from 'react'
import { useQuery } from '#apollo/react-hooks'
// Custom layout
import Layout from "../components/layout"
import '../sass/styles.scss'
// Data Query
import STATEMENTS_QUERY from '../graphql/statements'
function StatementCall(context) {
const { loading, error, data } = useQuery(STATEMENTS_QUERY, {});
return (
<Layout>
<div className="container">
<div className="row spaces">
<div className="col-md-12">
<p>Testing</p>
{data.statements.data.map((statement, index) => (
<div>
<p>{statement.id}</p>
<p>{statement.title}</p>
</div>
))}
</div>
</div>
</div>
</Layout>
)
}
export default StatementCall
graphql/statements.js:
import gql from 'graphql-tag';
const STATEMENTS_QUERY = gql`
query {
statements(filter: {destination: 1991}) {
data {
id
title
body
}
}
}
`;
export default STATEMENTS_QUERY;
You could check if the results are loading, before you try to render them.
Example:
function StatementCall(context) {
const { loading, error, data } = useQuery(STATEMENTS_QUERY, {});
if (loading) {
return <p>Loading...</p>;
}
if (error) {
// Handle error?
return <p>{error}</p>;
}
return (
<Layout>
<div className="container">
<div className="row spaces">
<div className="col-md-12">
<p>Testing</p>
{data.statements.data.map((statement, index) => (
<div>
<p>{statement.id}</p>
<p>{statement.title}</p>
</div>
))}
</div>
</div>
</div>
</Layout>
)
}
Check the example in useQuery docs.