React Swiper 6.8.4添加筛选功能后仅调整窗口或触发筛选时显示幻灯片
问题原因
Swiper 首次初始化时,你的filteredType状态默认是空数组,没有可渲染的滑块元素,Swiper会基于空列表计算布局尺寸。后续filteredType被赋值为全量数据后,Swiper默认不会监听子元素变化自动重算布局,只有窗口 resize、筛选操作触发状态更新时才会被动触发重绘,因此出现首次加载不显示的问题。
解决方案
你可以按以下步骤修改代码,即可修复初始化显示异常的问题:
- 将
filteredType的初始值直接设置为allData,匹配你type为空时显示全部数据的逻辑,避免首次渲染无数据 - 给Swiper组件开启
observer和observeParents配置项,开启后Swiper会自动监听内部DOM变化,自动重新计算布局 - 可选:如果存在筛选后滑块位置偏移的问题,可以在筛选数据更新后手动调用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
相关产品推荐
相关产品推荐

