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

React Swiper 6.8.4添加筛选功能后仅调整窗口或触发筛选时显示幻灯片

问题原因

Swiper 首次初始化时,你的filteredType状态默认是空数组,没有可渲染的滑块元素,Swiper会基于空列表计算布局尺寸。后续filteredType被赋值为全量数据后,Swiper默认不会监听子元素变化自动重算布局,只有窗口 resize、筛选操作触发状态更新时才会被动触发重绘,因此出现首次加载不显示的问题。

解决方案

你可以按以下步骤修改代码,即可修复初始化显示异常的问题:

  1. 将filteredType的初始值直接设置为allData,匹配你type为空时显示全部数据的逻辑,避免首次渲染无数据
  2. 给Swiper组件开启observer和observeParents配置项,开启后Swiper会自动监听内部DOM变化,自动重新计算布局
  3. 可选:如果存在筛选后滑块位置偏移的问题,可以在筛选数据更新后手动调用Swiper实例的update、slideTo方法重置状态

修改后完整代码

import React, { useState, useEffect, useRef } from "react";
import allData from '../allData';
import { Swiper, SwiperSlide } from 'swiper/react';
import SwiperCore, { Autoplay,Navigation, Pagination, Controller, Thumbs } from 'swiper';
import 'swiper/swiper-bundle.css';
import './styles.css';

SwiperCore.use([Autoplay,Navigation, Pagination, Controller, Thumbs]);

const project = [
  { type: "Web" },
  { type: "3D" },
  { type: "Photography" },
  { type: "Print" },
  { type: "Practice" }
];

export default function App() {
  const [type, setType] = useState([]);
  // 修正初始值为allData,避免首次渲染空
  const [filteredType, setFilteredType] = useState(allData);
  const swiperRef = useRef(null);
  const [show, toggleShow] = useState(false);

  const handleChange = e => {
    if (e.target.checked) {
      setType([...type, e.target.value]);
    } else {
      setType(type.filter(id => id !== e.target.value));
    }
  };

  useEffect(() => {
    if (type.length === 0) {
      setFilteredType(allData);
    } else {
      setFilteredType(
        allData.filter(project =>
          type.some(category => [project.type].flat().includes(category))
        )
      );
    }
  }, [type]);

  // 数据更新后手动重置Swiper状态
  useEffect(() => {
    if (swiperRef.current) {
      swiperRef.current.update();
      swiperRef.current.slideTo(0);
    }
  }, [filteredType]);

  return (
    <div>
      <Swiper 
        // 开启DOM监听自动更新布局
        observer={true}
        observeParents={true}
        onSwiper={(swiper) => swiperRef.current = swiper}
        slidesPerView={'auto'} 
        onSlideChange={() => toggleShow(false)}
        loop={false} 
        centeredSlides={true} 
        direction={'horizontal'}
        spaceBetween={100}
        slideToClickedSlide={true}
        pagination={{
          type: "fraction"
        }} 
        className="mySwiper"
      >
        {filteredType.map((project) => (
          <SwiperSlide className="swiper-slide" key={project.id}>
            <img className="img-slide" src={project.image} alt={project.title}/>
            <div className="project-info">
              {show && <div className="info">{project.info}</div>}
              <div className="text">{project.id} / {project.title}</div>
            </div>
          </SwiperSlide>
        ))}
      </Swiper>

      <div className="filterbox">
          {project.map((projectItem, index) => (
            <label className={`tag${projectItem.type}`} key={index}>  
              <input
                name="type"
                type="checkbox"
                value={projectItem.type}
                onChange={handleChange}
              />
              <span className="tags">{projectItem.type}</span> 
            </label>
          ))}
        </div>
        <button  className="info-button" onClick={() => toggleShow(!show)}>Info</button>    
    </div>
  );
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 09:06:03