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

React调用clickAction函数时滑块切换出现屏幕闪烁问题求助

React滑块组件切换时屏幕闪烁问题

我正在开发一个React滑块组件,点击项目切换到第二个项目时,调用clickAction()函数会出现屏幕闪烁,问题刚好在调用这个函数时发生。


相关代码

VerticalCarousel组件(点击事件处理部分)

const VerticalCarousel = ({ clickActionTransfer }) => {
        .
        ..
        ...
     
         <button
               data-glitch={item.type}
               type="button"
               onClick={clickActionTransfer}
               key={i}>
               CLICK
               {item.type}
         </button>
    };

Slider组件代码

import React, { useState, useEffect } from "react";
import VerticalCarousel from "./carousel/VerticalCarousel";

const Slider = ({ getData, idd, clickAction, children }) => {
  const [displayTitleState, setDisplayTitleState] = useState(true);
  const [displayCarouselState, setDisplayCarouselState] = useState(true);

  const [currentIndex, setCurrentIndex] = useState(0);
  const [length, setLength] = useState(children.length);

  const handleSlideClick = () => {
    if (currentIndex < length - 1) {
      setCurrentIndex((prevState) => prevState + 1);
    }
    setDisplayCarouselState(false);
    setTimeout(() => {
      setDisplayTitleState(false);
      clickAction();
    }, 1000);
    setTimeout(() => {
      setDisplayTitleState(true);
      setDisplayCarouselState(true);
    }, 2600);
  };
  useEffect(() => {
    setLength(children.length);
  }, [children]);

  return (
    <div className="slider__container">
      {getData.map((i) => {
        return (
          idd === i.id && (
            <div key={i.id}>
              <div
                style={{
                  transform: `translateX(-${currentIndex * 100}%)`,
                  display: "flex",
                  transition: "all .5s linear",
                }}
              >
                {children}
              </div>
              <div className="slider__content">
                <div
                  className={
                    "slider__left " + (i.theme === "light" ? "light-theme" : "")
                  }
                >
                  <div className="slider__progressBar">
                    {i.progressBar.nb1}
                    <span className="slider__progressBar-lightTxt">
                      {i.progressBar.nb1}
                    </span>
                    {i.progressBar.text}
                  </div>
                  <h1 className={displayTitleState ? "showTitle" : "hideTitle"}>
                    {i.title}
                  </h1>
                </div>
                <div
                  className={`slider__right ${
                    displayCarouselState ? "showCarousel" : "hideCarousel"
                  } ${i.theme === "light" ? "light-theme" : ""}`}
                >
                  <VerticalCarousel
                    data={i.slider}
                    clickActionTransfer={handleSlideClick}
                  />
                </div>
              </div>
            </div>
          )
        );
      })}
    </div>
  );
};

export default Slider;

App.js代码

import React, { useState, useEffect } from "react";
import Slider from "./Slider";
import "./App.scss";

function App() {
  const [loadSlide, setLoadSlide] = useState(0);
  const [data, setData] = useState([]);

  const handleclick = () => {
    setLoadSlide(loadSlide + 1);
  };

  useEffect(() => {
    setLoadSlide((loadSlide) => loadSlide + 1);
    fetch("/data.json")
      .then((response) => response.json())
      .then((json) => {
        setData(json.lvmh.sliders);
      });
  }, []);

  return (
    <div className="App">
      <div
        className={
          "slider " +
          (loadSlide >= 1 &&
            loadSlide <= data.length &&
            loadSlide + 1 &&
            `ifSlider`)
        }
      >
        <>
          {loadSlide >= 0 && loadSlide <= data.length && loadSlide + 1 && (
            <Slider clickAction={handleclick} idd={loadSlide} getData={data}>
              {data.map((img) => {
                return (
                  <img className="slider__bg---- " src={img.img} alt="" />
                );
              })}
            </Slider>
          )}
        </>
      </div>
    </div>
  );
}
export default App;

问题分析与解决方案

核心问题

  1. 闭包导致状态更新异常:handleclick中直接使用loadSlide + 1会捕获初始状态值,导致状态更新逻辑出错,引发组件不必要的重复渲染。
  2. 组件频繁卸载重建:App中的条件渲染逻辑会在loadSlide变化时卸载并重新挂载Slider组件,打断内部动画状态,直接导致屏幕闪烁。

修复步骤

  1. 修复状态更新的闭包问题
    改用函数式更新获取最新状态值,避免闭包陷阱:

    const handleclick = () => {
      setLoadSlide(prev => prev + 1);
    };
    
  2. 避免Slider组件卸载重建
    简化条件渲染逻辑,只要数据加载完成就保留Slider实例,通过idd控制显示内容,同时给列表项添加唯一key:

    return (
      <div className="App">
        <div
          className={`slider ${loadSlide >= 1 && loadSlide <= data.length ? 'ifSlider' : ''}`}
        >
          {data.length > 0 && (
            <Slider clickAction={handleclick} idd={loadSlide} getData={data}>
              {data.map((img) => (
                <img key={img.id} className="slider__bg---- " src={img.img} alt="" />
              ))}
            </Slider>
          )}
        </div>
      </div>
    );
    
  3. 优化Slider组件的状态逻辑
    移除冗余的dataSlider状态,直接使用传入的getData prop,减少不必要的状态同步操作(已在上方修改后的Slider代码中体现)。

以上修改可解决状态更新异常和组件频繁重建的问题,彻底消除屏幕闪烁现象。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 07:10:32