You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Flickity Slider初始渲染flickityRef未定义致点击跳转失效

React Flickity Slider 点击跳转异常问题

问题详情

  • 已解决初始渲染时flickityRef返回undefined导致onEngagement回调在组件重渲染前无法工作的问题。
  • 当前新问题:当滑块内渲染带筛选功能的组件时,初始渲染阶段点击滑块元素无法跳转至对应位置;但点击筛选触发组件重渲染、或开发环境热重载后,该功能恢复正常;渲染其他组件时无此问题。

组件代码

import React, { useRef, useEffect, useCallback } from "react";
import { isBrowser } from "@cryos/helpers/browser.helper";
import Flickity from "flickity";

export interface ICarouselProps {
  content: JSX.Element[] | undefined;
  previewNext?: boolean;
  startIndex?: number;
  fullscreen?: boolean;
  cellAlign?: "left" | "right" | "center";
  onCarouselChangeCallback?: (index: number) => void;
  getFlickityRef?: (ref: Flickity) => void;
  /**
   * Triggered when certain events happen for tracking purposes.
   */
  onEngagement?: () => void;
  dontChangeSlideOnClick?: boolean;
}

export const Carousel = React.memo<ICarouselProps>((props) => {
  const {
    content,
    previewNext,
    onCarouselChangeCallback,
    startIndex,
    fullscreen,
    onEngagement,
    dontChangeSlideOnClick,
    getFlickityRef,
  } = props;

  const FlickityComponent = isBrowser ? require("react-flickity-component") : "div";

  const flickityRef = useRef<Flickity>();

  let cellAlignment = previewNext ? "left" : "center";
  cellAlignment = props.cellAlign ? props.cellAlign : cellAlignment;

  const handleOnEngagement = useCallback(() => {
    onEngagement?.();
  }, [onEngagement]);

  const setFlickityRef = useCallback(
    (ref: Flickity) => {
      flickityRef.current?.off("change", handleOnEngagement);

      flickityRef.current = ref;
      if (getFlickityRef) {
        getFlickityRef(ref);
      }

      flickityRef.current?.on("change", handleOnEngagement);
    },
    [handleOnEngagement, getFlickityRef],
  );

  useEffect(() => {
    const flickity = flickityRef.current;

    const onChange = (index?: number) => {
      if (typeof index !== "undefined" && onCarouselChangeCallback) {
        onCarouselChangeCallback(index);
      }
    };

    const onStaticClick = (_event?: Event, _pointer?: Element | Touch, _cellElement?: Element, cellIndex?: number) => {
      if (typeof cellIndex !== "undefined" && !dontChangeSlideOnClick && flickity) {
        flickity.select(cellIndex);
      }
    };

    if (flickity) {
      flickity.on("change", onChange);
      flickity.on("staticClick", onStaticClick);
    }

    return () => {
      if (flickity) {
        flickity.off("change", onChange);
        flickity.off("staticClick", onStaticClick);
      }
    };
  }, [content, onCarouselChangeCallback, dontChangeSlideOnClick]);

  return (
    <>
      {content && content.length > 1 ? (
        <div
          className={`c-carousel ${previewNext ? "c-carousel--preview" : ""} ${
            fullscreen ? "c-carousel--fullscreen" : ""
          }`}
        >
          <FlickityComponent
            flickityRef={setFlickityRef}
            className="c-carousel__flickity"
            options={{
              dragThreshold: 10,
              imagesLoaded: true,
              arrowShape: "M 20,50 L 70,100 L 75,95 L 30,50  L 75,5 L 70,0 Z",
              cellAlign: cellAlignment,
              initialIndex: startIndex || 0,
              setGallerySize: true,
            }}
          >
            {content}
          </FlickityComponent>
        </div>
      ) : (
        <>{content && content[0]}</>
      )}
    </>
  );
});

Carousel.displayName = "Carousel";

内容的提问来源于stack exchange,提问作者ComCool

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 20:35:10