I faced an unexpected issue while working with static pages in a Next.js project. It was a simple carousel component that received images via props and managed its internal state.
But after navigating to another page, the carousel began to act strangely. The wrong image was selected. Sometimes, it broke entirely. At first glance, nothing had changed — yet clearly, something had.
This happens because frameworks hide a lot of the complex stuff behind the scenes. It’s not a bug — just one of those things that can trip you up if you don’t understand what’s happening.
Going down the rabbit hole.
When we switch to another dynamic page, the route stays the same, so Next.js doesn't remount the main component. Instead, it just changes the props.
Due to this, all the child components in the tree are preserved along with their states.
React tree on first load
<App>
└── [slug].tsx (slug = "product-a")
└── <Gallery images={["a1.jpg", "a2.jpg"]} />
The gallery is rendered with images for "product-a". The selectedImageIndex
is initialized to 0.
User makes a route change
<App>
└── [slug].tsx (slug = "product-b")
└── <Gallery images={["b1.jpg", "b2.jpg"]} />
The Gallery component was not unmounted during navigation. If the user had previously selected image index 1 on product-a
, that same index remains selected after navigating to product-b
.
And the functionality breaks if product-b
doesn't have any image to serve on index 1.
This behavior is influenced by both React and Next.js.
The Solution
Instead of Googling, I went straight to ChatGPT like most people do nowadays. There were a couple of straightforward ways to fix it. I implemented one and noted the other as a solid alternative.
- Include a unique key whenever calling the gallery component instance.
- Add a useEffect that resets the internal state whenever the props, specifically the images, change.
I haven't tried the second option, but I believe it would provide the necessary granular control for some components.
Provinding the key
<App>
└── [slug].tsx (slug = "product-b")
└── <Gallery key="product-b" images={["b1.jpg", "b2.jpg"]} />
The key would change with the product, causing the component to unmount and remount. Upon successful operation, all the states would be set to default.
This approach was able to solve my issue effectively.
To wrap things up
The issue reminds us that modern frameworks do a lot of heavy lifting behind the scenes, which is fantastic! However, it also highlights the importance for developers to understand what's happening under the hood.
By knowing how React and Next.js handle component lifecycles and state, we can avoid these pitfalls and write more predictable, robust applications.
If you’ve encountered similar challenges or have tips to share, I’d love to hear about them
Top comments (0)