Show or hide Carousel item depending on index | React

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.

Leave a Comment

Your email address will not be published.

Scroll to Top