I'm using next.js and I was hoping to see my gallery collection like this on click of one of my images which is not happening. Actually, it's like I have just used a normal component, because literally nothing is happening when I click one of my images. Please help.
// this is my app component
import SimpleReactLightbox from 'simple-react-lightbox'
const MyApp = ()=>{
return(
<SimpleReactLightbox>
<Component {...pageProps} />
</SimpleReactLightbox>
)
}
// this is my collection
import { CollectionStyledTypography } from './styles/collectionStyledComponents'
import { SRLWrapper } from 'simple-react-lightbox'
import Image from 'next/image'
const Collection = ({ imagesList = [] }) => {
return (
<SRLWrapper>
<div style={{ margin: '50px' }}>
{imagesList.map((image, index) => (
<CollectionStyledTypography component="div" key={index}>
<Image src={image.src} alt={image.alt} layout="fill" />
</CollectionStyledTypography>
))}
</div>
</SRLWrapper>
)
}
export default Collection
SRL is no longer being developed, and it won't work in React 18. You will have to downgrade to 17 to make it work. I am facing the same problem, nothing happens when i click on an image.
Related
Below snippet is taken from _app.tsx file. I know that having Script component inside the Head component is wrong but this buggy code is blocking the sweetalert library (which I am using in another page to render pop up) from dynamically inserting the CSS rules.
import Head from "next/head";
import Script from "next/script";
import type { AppProps } from "next/app";
export default function App({ Component, pageProps }: AppProps) {
return (
<>
<Head>
<Script
id="branch-io"
strategy="afterInteractive"
dangerouslySetInnerHTML={{
__html: `(function(){console.log("hello world")}())`,
}}
/>
</Head>
<Component {...pageProps} />
</>
);
}
For example in this page when I click on the button the popup will be displayed without any CSS applied to it.
import swal from "sweetalert";
export default function Home() {
return (
<button
onClick={() => swal("Hello world!")}
style={{
width: "25vw",
height: "25vh",
color: "white",
backgroundColor: "red",
}}>
Patronus Potter
</button>
);
}
I can resolve the bug by correcting the mistake in the _app.tsx file but my question is why does it happen? Not able to pin point an answer to the question. Any pointers on how to investigate further would be appreciated or Does anybody know why this happens?
So i've been following a tutorial and trying to teach myself next.js with lazy loading slider and tailwindcss.. I am a beginner but i have made ecommerce sites and stuff to teach myself.. but this tutorial was going great until this!but Ive tried everything i know and googled it every which way to try to fix this issue!! My images were showing perfectly before i added the - const setCurrent up to the if !Array
if i delete that the images show back up... im so confused ive gone through everything - also the "Gallery" even disapeared once i added that section
and i put it all on github incase someone can look at it to help me?? https://github.com/Jessica19882/firebird
i have deleted the
const current up to the !Array part and images showed back up i have tried rewriting it as another post said but that didnt work ive checked and zoomed into the video tutorial to make sure everything was right and it is... i have checked all the other pages index.js app.js and stuff to make sure i had it just like his and it is!!
slider.js
import { SliderData } from './SliderData'
import React, { useState } from 'react'
import Image from 'next/image'
const Slider = ({ slides }) => {
const [current, setCurrent] = useState(0)
const length = slides?.length
const nextSlide = () => {
setCurrent(current === length - 1 ? 0 : current + 1)
}
const prevSlide = () => {
setCurrent(current === 0 ? length - 1 : current - 1)
}
if (!Array.isArray(slides) || slides.length <= 0) {
return null
}
return (
<div id='gallery'>
<h1>Gallery</h1>
<div>
{SliderData.map((slide, index) => {
return (
<div
key={index}
className={
index === current
? 'opacity-[1] ease-in duration-1000'
: 'opacity-0'
}>
<Image
src={slide.image}
alt='/'
width='1440'
height='600'
style={{ objectFit: 'cover' }}
/>
</div>
)
})}
</div>
</div>
)
}
export default Slider
index.js
import Head from 'next/head'
import Hero from '../components/Hero'
import Slider from '../components/Slider'
import SliderData from '../components/SliderData'
export default function Home() {
return (
<div>
<Head>
<title>Firebird Sounds</title>
<meta name='description' content='firebird sounds' />
<meta name='viewport' content='width=device-width, initial-scale=1' />
<link rel='icon' href='/favicon.ico' />
</Head>
<Hero
heading='Firebird Sounds - Audio & Video Distribution'
message='Audio and Video Distribution with a menu of
Services: Marketing, PR, Global rights management and creativity'
/>
<Slider Slides={SliderData} />
</div>
)
}
SliderData.js
export const SliderData = [
{
image:
'https://images.unsplash.com/photo-1466428996289-fb355538da1b?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MTl8fG11c2ljJTIwZGlzdHJpYnV0aW9ufGVufDB8fDB8fA%3D%3D&auto=format&fit=crop&w=500&q=60',
},
{
image: '/images/FirebirdSounds.jpg',
},
{
image:
'https://images.unsplash.com/photo-1460667262436-cf19894f4774?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxzZWFyY2h8NjZ8fG11c2ljJTIwZGlzdHJpYnV0aW9ufGVufDB8fDB8fA%3D%3D&auto=format&fit=crop&w=500&q=60',
},
{
image: '/images/guitar.jpg',
},
{
image: '/images/firebird.png',
},
]
app.js
import Navbar from '../components/Navbar'
import '../styles/globals.css'
export default function App({ Component, pageProps }) {
return (
<>
<Navbar />
<Component {...pageProps} />
</>
)
}
https://www.youtube.com/watch?fbclid=IwAR2jl5qYoIsaFZQ26MumbFcCYv5t3eYxcqVKgm4xAsxilhEkAzSNoUB0fzE&v=HVyct9EUNP8&feature=youtu.be
I figured it out I needed to put the
Slider slides={SliderData}/>
into _app.js not index.js or both but its working again!
I am trying to create a carousel in a next.js app, using framer motion and tailwindcss.
import { motion } from "framer-motion";
import { useRef, useEffect, useState, useCallback, useLayoutEffect } from "react";
function Carousel({ images }) {
const [width, setWidth] = useState(0);
const carousel = useRef();
useLayoutEffect(() => {
setWidth(carousel.current.scrollWidth - carousel.current.offsetWidth);
}, []);
return (
<motion.div
ref={carousel}
className="min-w-full h-96 overflow-hidden cursor-grab bg-primary my-5"
whileTap={{ cursor: "grabbing" }}
>
<motion.div
drag="x"
dragConstraints={{ right: 0, left: -width }}
className="flex items-center justify-center min-w-max h-full"
>
{images.map((image) => {
return (
<motion.div key={image.src} className="h-5/6 mx-8 relative">
<img
src={image.src}
alt=""
className="h-full rounded-lg pointer-events-none"
/>
</motion.div>
);
})}
</motion.div>
</motion.div>
);
}
export default Carousel;
The thing is that when I navigate to the page with the carousel from within the app (using next's <Link>), the scrollWidth is messed up - evaluating a much smaller number, thus my right dragConstraints is incorrect and I can't drag much more than what is currently visible on the screen. Only after I refresh the page scrollWidth is correct and the dragging constraint and all is properly working.
Still learning frontend, so I would assume I am missing something obvious, but what I have tried is:
useEffect and useLayoutEffect
useRef and callback ref
passing carousel, carousel.current to the dependency array
not use the next <Link>, but that is just like manually refreshing
the page (not cool)
replacing tailwind with plain CSS
I would appreciate any hint/advice ✌️ since my web searches didn't help me solve this and only brought me more confusion regarding the origin of the issue.
I would like to implement a loading screen on first render in next.js but when I load the page the body content flashes for a moment before the loader starts. I'm not sure what should I write differently. If I change the initial state to true that doesn't seem to work either because then the wrapper styles for the loader won't apply and instead I get a blank html page with the spinner on the top left corner.
_app.js
function MyApp({ Component, pageProps }) {
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
setIsLoading(true);
setTimeout(() => {
setIsLoading(false);
}, 3000);
}, []);
return (
<>
{isLoading ? (
<Loader />
) : (
<ThemeProvider theme={dark}>
<GlobalStyles />
<Component {...pageProps} />;
</ThemeProvider>
)}
</>
);
}
export default MyApp;
Loader div style:
.loader-wrapper{
width:100%;
height: 100vh;
background: ${({ theme }) => theme.colors.body};
display: flex;
align-items: center;
justify-content: center;
}
Loader Component
export const Loader = () => {
return (
<div className='loader-wrapper'>
<Oval
ariaLabel='loading-indicator'
height={100}
width={100}
strokeWidth={2}
color='#32ffa9'
secondaryColor='#1f1f1fdc'
/>
</div>
);
};
Thats because useEffect called after component rendered.
Life cycle:
1- Initial state of isLoading = false <ThemeProvider /> rendered (body content flashes for a moment)
2- useEffect called and isLoading = true
3- Component re-rendered but this time it will render <Loader />
4- 3 second later setTimeout callback called isLoading = false
5- Component re-rendered and it will render <ThemeProvider /> again
So you should make your inital isLoading = true, I couldn't understand the issue "wrapper styles for the loader won't apply." can you describe it more?
I made codesandbox example for you which I think works as you want (it's not NextJS app but since all the code is pure React it will work on both)
I'm currently trying to incorporate a loader component to a site built with NextJS. I would like to use Suspense to show a loading screen may it be after refreshing the page or changing routes.
This is how my code goes:
import Head from 'next/head'
import { Loader } from '../components/loader'
const { Suspense } = require('React')
function MyApp({ Component, pageProps }) {
return (
<>
<Suspense fallback={<Loader />}>
<Head>
.... some codes such as meta tags, title tags ....
</Head>
<Component {...pageProps} />;
</Suspense>
</>
)
}
My problem is I get an error that says ReactDOMServer does not yet support Suspense. but I would like to use Suspense to enable a loading screen on my page. Much like this website
You can use React 18 features like suspense in Next.js Advanced Features. Obviously it's still experimental and might cause issues with you application.
npm install next#latest react#rc react-dom#rc
To enable, use the experimental flag concurrentFeatures: true
// next.config.js
module.exports = {
experimental: {
concurrentFeatures: true,
},
}
Once enabled, you can use Suspense and SSR streaming for all pages.
import dynamic from 'next/dynamic'
import { lazy, Suspense } from 'react'
import Content from '../components/content'
// These two ways are identical:
const Profile = dynamic(() => import('./profile'), { suspense: true })
const Footer = lazy(() => import('./footer'))
export default function Home() {
return (
<div>
<Suspense fallback={<Spinner />}>
{/* A component that uses Suspense-based */}
<Content />
</Suspense>
<Suspense fallback={<Spinner />}>
<Profile />
</Suspense>
<Suspense fallback={<Spinner />}>
<Footer />
</Suspense>
</div>
)
}
I had a similar issue. I ended up simulating the Suspense with a combination of setState & componentDidMount
render(){
return this.state.browser ? <Component/> : <Placeholder/>
}
componentDidMount(){
this.setState({browser: true})
}
I hope it helps.