The problem
Your problem stems from how you’re trying to do your logic against state variables. There’s no connection between your state and your ShowTitle
component, other than referring to them. Whenever you page through the carousel, you’re changing both state variables so they will always be the same.
Unfortunately, the library you’ve chosen for your carousel forces you to rely on an index, so I would suggest you use the index
argument on the map function to assign indexes to your ShowTitle
components.
Note: React will warn you if you try to use indexes for keys, as that has the potential for strange behavior. Keep using the id for that.
The solution
function ImageSlider({ imageList }) {
const [currentSlide, setCurrentSlide] = useState(0);
// Since this is a component, you need to destructure props
function ShowTitle({ title, id }) {
// If the index is on focused
if (id === currentSlide) {
return <p>{title}</p>;
}
// Otherwise return empty
return <p></p>;
}
// I'm not sure what props you're going to get here; it'll be whatever
// the Slider provides you with when afterChange is fired
function handleAfterChange(index) {
setCurrentSlide(index);
}
return (
<Slider
className="center"
centerMode={true}
infinite={true}
autoplay={true}
autoplaySpeed={2000}
slidesToShow={3}
slidesToScroll={1}
afterChange={handleAfterChange}
>
{/* Add index argument to map here (this is provided automatically) */}
{imageList.map((image, index) => (
<div key={image.id} id={image.id}>
<img
alt="image"
width={270}
height={120}
src={image.url}
/>
{/* Add index prop to ShowTitle */}
<ShowTitle title={image.title} index={index} />
</div>
))}
</Slider>
);
}
A suggestion
If you want to optimize this you can completely do away with the ShowTitle
component and conditionally render your p
tag.
...
{index === currentSlide ? <p>{image.title}</p> : <p></p>}
...
The why of it all
When react renders all of your code, it is going to call the ShowTitle
component, because it is, in fact, a component with the way you’ve written this. A function component is just a function that takes in props as its argument, and returns some JSX. Since it will call this for every loop over map, it will compare the currently set state (which doesn’t change until the user does something to invoke afterChange
) so it will compare the same state variables every time, hence why all of the titles show. When you do invoke afterChange
, it always sets the two state variables to the same thing and changing state causes a rerender. This is why all of the titles are always present.
To rectify this, you need to have the rendering of a particular slide tied to the currently selected index in the carousel, and you need your component to know where it is in the carousel (by way of the index in the map function) to be able to compare to the currently selected index.
CLICK HERE to find out more related problems solutions.