swiper/react autoPlay且数据源为动态获取的时候 保持显示当前数据 防止出现数据突然变化的情况

需求:swiper自动滚动,且数据是从ws接口取的,每秒都会更新,需要保证在滚动的时候始终显示当前数据,不出现突然变成别的数据的情况 

我写的是手机端的页面 所以一屏只出现1.5条数据

html部分

const options = {
  observer: true,
  observeParents: true,
  speed: 1500,
  loop: true,
  slidesPerView: 'auto',
  spaceBetween: 10,
  freeMode: true,
  autoplay: {
    delay: 1500,
    stopOnLastSlide: false,
    disableOnInteraction: false,
  },
} as const;

const swiperRef = useRef<SwiperType | null>(null);
const [currentIndex, setCurrentIndex] = useState(0);

// 这是从ws接口取过来的数据
const { socketData: solSocketData } = useGetSolBroadcast({
    currentIndex,
});

return (
    <div>
      {!!realData.length && realData.length > 1 && (
        <Swiper
          centeredSlides={false}
          modules={[Autoplay]}
          {...options}
          onInit={(swiper) => {
            swiperRef.current = swiper;
          }}
          onSlideChange={(v) => setCurrentIndex(v.realIndex)}
        >
          {realData.map((item, i) => (
            <SwiperSlide
              // key一定得是索引值
              key={i}
              style={{
                width: `${item.width}px`,
              }}
            >
              <div
                style={{
                  width: `${item.width}px`,
                }}
              >
                {item.data}
              </div>
            </SwiperSlide>
          ))}
        </Swiper>
      )}
    </div>
  );

获取数据的部分

import { useThrottleEffect } from 'ahooks';

export function useGetSolBroadcast({
  currentIndex,
}: {
  currentIndex: number;
}) {
  // 传给swiper组件的数据
  const [socketData, setSocketData] = useState<SocketData>([]);
  // 从ws接口取到的数据
  const { messageHistory } = useSolWebSocketStore();
  // 最多显示几条数据
  const limit = 8;

  useThrottleEffect(
    () => {
      // 把数据转换成需要的格式
      const parsed = messageHistory
        .map((item) => {
          return parseMessage({
            type: item.is_buy ? MessageType.Buy : MessageType.Sell,
            data: item,
          });
        })
        .filter((item) => item !== undefined);
      if (messageHistory.length < limit) {
        // 当数据量少于显示的数量上限时 直接赋值
        setSocketData(parsed);
      } else if (messageHistory.length >= limit) {
        setSocketData((pre) => setNewData(pre, parsed));
      }
    },
    [messageHistory, currentIndex],
    { trailing: false, wait: socketData.length < limit ? 1000 : 3000 },
  );

  const setNewData = (pre: SocketData, messageList: SocketData) => {
    // 避免新取到的数据和已有数据重复
    const list = messageList
      ?.filter((item) => !pre?.find((cItem) => cItem?.id === item?.id || cItem?.user === item?.user))
      .filter((item) => item !== undefined);

    if (isNumber(currentIndex)) {
      // 保持当前index-1, index, index+1对应的数据不变 其他索引的数据替换成新的
      if (currentIndex === 0) {
        return [pre[0], pre[1], ...list.slice(0, limit - 3), pre[pre.length - 1]];
      } else if (currentIndex === limit - 1) {
        return [pre[0], ...list.slice(0, limit - 3), ...pre.slice(-2)];
      } else {
        return [
          ...list.slice(0, currentIndex - 1),
          ...pre.slice(currentIndex - 1, currentIndex + 2),
          ...list.slice(currentIndex - 1, limit - 3),
        ];
      }
    }
    return [];
  };

  return { socketData };
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值