0

I'm using redux-sagas for store management, so when the request state is success, it should slide to the right using the ref. However, this behavior is not being reflected. What happens is that it doesn't slide to the right; I have to go back and forth with the arrows to display the data.

Home.jsx

  const Component = ({
  cohorts,
  selectedAcademy,
  cohortStates,
}: ComponentProps) => {
  const dispatch = useDispatch();
  const navigate = useNavigate();
  const refToSlider: any = useRef(null);
  const { isMobile } = useWindowSize();
  const [isLoading, setIsLoading] = useState<boolean>(true);
  const [thereAreItems, setThereAreItems] = useState<boolean>(true);
  const [items, setItems] = useState<CohortDto[]>([]);

  const fetchData = ({ page, filterBy }: FetchData) => {
    console.log(page, "context pagedata");
    let payload: { [key: string]: PaginationDto } = {
      cohorts: {
        limit: 4,
        offset: 4 * page,
        filterBy: {
          ...(filterBy ? filterBy : {}),
          active: true,
        },
      },
    };

    /*    const sortBy = page % 2 === 0 ? "viewCount" : "created_at";
    const sortDirection = "desc"; */

    payload = Object.entries(payload).reduce((acc, [key, value]) => {
      acc[key] = { ...value /* sortBy, sortDirection  */ };
      return acc;
    }, {});
    dispatch(
      getCohortsByAcademy({ _id: selectedAcademy._id, ...payload.cohorts })
    );
  };
  const onOffsetChange = (newIndex) => {
    fetchData({ page: newIndex });
  };
  useEffect(() => {
    return () => {
      dispatch(resetGetAllCohorts());
    };
  }, []);

  useEffect(() => {
    if (!isLoading && !!cohorts) {
      setItems((state) => [...state, ...cohorts]);
      setThereAreItems(!!cohorts && cohorts?.length === 4);
    }
  }, [cohorts, isLoading]);
  useEffect(() => {
    if (refToSlider.current && cohortStates.success) {
      dispatch(resetGetAllCohortsStates());
      refToSlider.current.nextSlide();
    }
    setIsLoading(cohortStates.loading);
  }, [cohortStates, refToSlider, dispatch]);

  return (
    <>
      <FlexContainer direction="column" gap="8px">
        <BannerTitle size="16px">Próximos Cohorts</BannerTitle>
        {!items ? (
          <Loader color="LightBlue"></Loader>
        ) : (
          <Slider
            ref={refToSlider}
            moreItems={thereAreItems}
            limit={4}
            onBeforeChange={onOffsetChange}
            isLoading={isLoading}
          >
            {items.length > 0 ? (
              items
                /* .filter(
                  (cohort) =>
                    cohort.active &&
                    cohort.academy === selectedAcademy?._id &&
                    !cohort.hidden
                ) */
                .map((cohort) => (
                  <Slide
                    onClick={() => {
                      dispatch(addClick({ _id: cohort._id }));
                      navigate(`/dashboard/cohort/${cohort._id}/home`);
                    }}
                    key={cohort._id}
                  >
                    <SlideImg
                      {...(isMobile && { style: { height: "200px" } })}
                      src={
                        cohort.picture ??
                        "https://repository-images.githubusercontent.com/410214337/070f2aba-d9d6-4699-b887-9a0f29015b1b"
                      }
                    ></SlideImg>
                    <SlideTitle>{cohort.name}</SlideTitle>
                    <FlexContainer align="center" gap="6px">
                      <FlexContainer align="center" gap="3px">
                        <DotContent></DotContent>
                        <SlideSubTitle>
                          {`Inicio: `}
                          {!!cohort.startDate && (
                            <span>
                              {new Date(cohort.startDate).toLocaleDateString(
                                "en-GB"
                              )}
                            </span>
                          )}
                        </SlideSubTitle>
                      </FlexContainer>
                      <FlexContainer align="center" gap="3px">
                        <DotContent></DotContent>
                        <SlideSubTitle>
                          {`Finaliza: `}
                          {!!cohort.endDate && (
                            <span>
                              {new Date(cohort.endDate).toLocaleDateString(
                                "en-GB"
                              )}
                            </span>
                          )}
                        </SlideSubTitle>
                      </FlexContainer>
                    </FlexContainer>
                  </Slide>
                ))
            ) : (
              <FlexContainer style={{ width: "100%" }} justify="center">
                <h2>No hay Cohorts</h2>
              </FlexContainer>
            )}
          </Slider>
        )}
      </FlexContainer>
    </>
  );
};

const states = ({ cohortStore, academyStore }) => {
  const { data: cohorts, states: cohortStates } = cohortStore.allCohorts;
  const { data: selectedAcademy } = academyStore.selected;
  return {
    cohorts,
    selectedAcademy,
    cohortStates,
  };
};

export default connect(states)(Component);

In the slider to display the data, I use the 'children' property. If the index plus the limit is greater than the number of items in the 'children' property, it executes the function to fetch more data. Otherwise, it moves forward by increasing the index.

Slider.jsx

import Slider from "react-slick";
import "slick-carousel/slick/slick.css";
import "slick-carousel/slick/slick-theme.css";
import "./style.css";
import { SlideBlur } from "./style";
import React, {
  forwardRef,
  useEffect,
  useImperativeHandle,
  useRef,
  useState,
} from "react";
import Loader from "../../../../components/Loader";
interface ComponentProps {
  children: any;
  disabled?: boolean;
  noElements?: boolean;
  onBeforeChange?: any;
  limit: number;
  moreItems?: boolean;
  isLoading?: boolean;
}

function SampleNextArrow(props) {
  const { className, style, onClick, loading } = props;
  return (
    <button disabled={loading} className={"slick-next-new"} onClick={onClick} />
  );
}

function SamplePrevArrow(props) {
  const { className, style, onClick, loading } = props;
  return (
    <button disabled={loading} className={"slick-prev-new"} onClick={onClick} />
  );
}

const Component = forwardRef(
  (
    {
      children,
      disabled,
      noElements,
      onBeforeChange,
      limit,
      moreItems,
      isLoading,
    }: ComponentProps,
    ref
  ) => {
    const sliderRef: any = useRef(null);
    const totalSlides = React.Children.count(children);
    const [currentIndex, setCurrentIndex] = useState(0);
    useImperativeHandle(
      ref,
      () => ({
        nextSlide: () => {
          if (sliderRef.current && !isLoading) {
            sliderRef.current.slickNext();
          }
        },
        prevSlide: () => {
          if (sliderRef.current && !isLoading) {
            sliderRef.current.showPreview();
          }
        },
      }),
      [sliderRef, isLoading]
    );
    const handleNextArrowClick = () => {
      if (!isLoading && !!moreItems) {
        setCurrentIndex((prevIndex) => prevIndex + 1);
      }
    };
    const handlePrevArrowClick = () => {
      if (!isLoading && currentIndex > 0) {
        setCurrentIndex((prevIndex) => prevIndex - 1);
        sliderRef.current.slickPrev();
      }
    };
    const settings = {
      dots: false,
      infinite: false,
      speed: 500,
      slidesToShow: limit,
      slidesToScroll: limit,
      responsive: [
        {
          breakpoint: 1024,
          settings: {
            slidesToShow: 4,
            slidesToScroll: 4,
          },
        },
        {
          breakpoint: 600,
          settings: {
            slidesToShow: 2,
            slidesToScroll: 2,
            initialSlide: 2,
          },
        },
        {
          breakpoint: 480,
          settings: {
            slidesToShow: 1,
            slidesToScroll: 1,
          },
        },
      ],
      arrows: true,
      className: `${!!disabled ? "fade" : ""}`,
    };

    useEffect(() => {
      if (currentIndex + limit >= totalSlides) {
        !!onBeforeChange && onBeforeChange(currentIndex);
      }
    }, [currentIndex, limit]);
    return (
      <>
        {!!disabled ? (
          <div
            style={{
              position: "relative",
              width: "100%",
              ...(!!noElements && { minHeight: "200px" }),
            }}
          >
            <SlideBlur></SlideBlur>
            <Slider {...settings}>{children}</Slider>
          </div>
        ) : (
          <div style={{ position: "relative" }}>
            <Slider ref={sliderRef} {...settings}>
              {children.length === 0 ? (
                <Loader color="LightBlue"></Loader>
              ) : (
                children
              )}
            </Slider>
            {!!moreItems && (
              <SampleNextArrow
                loading={isLoading}
                onClick={handleNextArrowClick}
              />
            )}
            {currentIndex > 0 && (
              <SamplePrevArrow
                loading={isLoading}
                onClick={handlePrevArrowClick}
              />
            )}
          </div>
        )}
      </>
    );
  }
);

export default Component;
Agustin R
  • 47
  • 6

0 Answers0