skip to Main Content

Here I want to display the current image when I click on the "fullscreen" span tag.

export default function CandidateSlider({ componentData }) {
  const [showModal, setShowModal] = useState(false);
  const [imgSrc, setImgSrc] = useState("");
  const [photoslider, setPhotoSlider] = useState([]);
  const [currentDataItem, setCurrentDataItem] = useState(null);

  const fetchData = async () => {
    let api_data = await fetchUtility(componentData?.api_url, []);
    setPhotoSlider(api_data);
  };

  useEffect(() => {
    fetchData();
  }, []);

  const changeModal = (src, modal_state) => {
    setImgSrc(src);
    setShowModal(modal_state);
  };

  const NextBtn = (props) => {
    const { className, onClick } = props;
    return <div className={className} onClick={onClick}></div>;
  };
  const PreviousBtn = (props) => {
    const { className, onClick } = props;
    return <div className={className} onClick={onClick}></div>;
  };

  var settings = {
    dots: true,
    infinite: true,
    speed: 500,
    slidesToShow: 1,
    slidesToScroll: 1,
    prevArrow: <PreviousBtn />,
    nextArrow: <NextBtn />,
  };

  return (
    <>
      <section className="n18_ele_candislider_comp" id="slick_slider">
        <div className="glide n18_candislider">
          <span
            className="fullscreen"
            onClick={() => {
            changeModal(currentDataItem, true);
            }}
          >
             <span className="fullscreen_labl">
                fullscreen
              </span>
          </span>

          <Slider {...settings}>
            {Object.keys(photoslider).map(([dataitem, index]) => {

              // Here's the problem.
              setCurrentDataItem(photoslider?.[dataitem]?.thumbnail);

              return (
                <>
                  <div key={index} className="consti_prty_slidr">
                    <div className="imgeSlidr" key={index}>
                      <img
                        width="100%"
                        height="100%"
                        src={photoslider?.[dataitem]?.thumbnail}
                      />
                    </div>
                    <p className="const_slidr_det">
                      {photoslider?.[dataitem]?.title}
                    </p>
                  </div>
                </>
              );
            })}
          </Slider>
        </div>
      </section>
    </>
  );
}

It is throwing an error: "Error: too many re-renders. React limits the number of renders to prevent an infinite loop."

This error occurs because I used setCurrentDataItem(photoslider?.[dataitem]?.thumbnail) inside the map function.

But without this, how can I access the current ‘dataitem’ outside of the map function?

2

Answers


  1. Changing state should only happen as a reaction to some event. Changing it in your render triggers a re-render and thus an infinite loop.

    Assuming Slider is the component from React Slick, use either of the slide change hooks to capture the current slide index.

    It also looks like api_data is an object but you initialise it as an array and really only seem interested in treating it like an array. I would map the object data to an array to make things easier

    const fetchData = async () => {
      const api_data = await fetchUtility(componentData?.api_url, []);
      setPhotoSlider(
        Object.entries(api_data).map(([_id, data]) => ({
          _id, // store the key as an `_id` property
          ...data,
        })),
      );
    };
    
    // ...
    
    const settings = {
      // ... your current settings, then add
      beforeChange: (_, next) => {
        setCurrentDataItem(photoslider[next].thumbnail);
      },
    };
    
    return (
      <>
        {/* ... */}
    
        <Slider {...settings}>
          {photoSlider.map(({ _id, thumbnail, title }) => (
            <div key={_id} className="consti_prty_slidr">
              <div className="imgeSlidr">
                <img width="100%" height="100%" src={thumbnail} />
              </div>
              <p className="const_slidr_det">{title}</p>
            </div>
          ))}
        </Slider>
    
        {/* ... */}
      </>
    );
    
    Login or Signup to reply.
  2. The reason that you are experiencing this issue, is because you are calling fetchData() within an useEffect(), where you probably want to call it in a useCallback() instead. useEffect() runs on every re-render. You have also not bound your useEffect() to any state dependencies, so every time the state changes, that effect will be run. This is why your code is infinite looping when you change the state within your template, as it fetches data again, and then rerenders, because you are setting photoSlider which is also part of your template.

    Put your fetchData() call into a useCallback() and perhaps have it depend on currentDataItem

      useCallback(() => {
        fetchData();
      }, [currentDataItem]);
    
    

    This way, when currentDataItem changes, the callback will be called.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search