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

React 18下替换react-swipeable-views依赖的技术方案咨询

React 18下替换react-swipeable-views实现Material UI轮播的解决方案

问题背景

使用Material UI开发轮播组件时,react-swipeable-views及react-swipeable-views-utils因不兼容React 18导致组件无法正常运行,需替换依赖并保留原有功能与UI风格。

可行方案

方案1:使用react-responsive-carousel(兼容React18,快速适配)

该库完全支持React18,能轻松与Material UI组件集成,保留自动播放、滑动切换、步进器控制等核心功能。

步骤:

  1. 安装依赖:
npm install react-responsive-carousel
  1. 替换原有代码,适配Material UI样式:
import * as React from 'react';
import { useTheme } from '@mui/material/styles';
import Box from '@mui/material/Box';
import MobileStepper from '@mui/material/MobileStepper';
import Paper from '@mui/material/Paper';
import Typography from '@mui/material/Typography';
import Button from '@mui/material/Button';
import KeyboardArrowLeft from '@mui/icons-material/KeyboardArrowLeft';
import KeyboardArrowRight from '@mui/icons-material/KeyboardArrowRight';
import { Carousel } from 'react-responsive-carousel';
import 'react-responsive-carousel/lib/styles/carousel.min.css';

const images = [
  {
    label: 'San Francisco – Oakland Bay Bridge, United States',
    imgPath:
      'https://images.unsplash.com/photo-1537944434965-cf4679d1a598?auto=format&fit=crop&',
  },
  {
    label: 'Bird',
    imgPath:
      'https://images.unsplash.com/photo-1538032746644-0212e812a9e7?auto=format&fit=crop&',
  },
  {
    label: 'Bali, Indonesia',
    imgPath:
      'https://images.unsplash.com/photo-1537996194471-e657df975ab4?auto=format&fit=crop&',
  },
  {
    label: 'Goč, Serbia',
    imgPath:
      'https://images.unsplash.com/photo-1512341689857-198e7e2f3ca8?auto=format&fit=crop&',
  },
];

function SwipeableTextMobileStepper() {
  const theme = useTheme();
  const [activeStep, setActiveStep] = React.useState(0);
  const maxSteps = images.length;

  const handleNext = () => {
    setActiveStep((prev) => (prev === maxSteps - 1 ? 0 : prev + 1));
  };

  const handleBack = () => {
    setActiveStep((prev) => (prev === 0 ? maxSteps - 1 : prev - 1));
  };

  const handleSlideChange = (index: number) => {
    setActiveStep(index);
  };

  return (
    <Box sx={{ maxWidth: 400, flexGrow: 1 }}>
      <Paper
        square
        elevation={0}
        sx={{
          display: 'flex',
          alignItems: 'center',
          height: 50,
          pl: 2,
          bgcolor: 'background.default',
        }}
      >
        <Typography>{images[activeStep].label}</Typography>
      </Paper>
      
      <Carousel
        selectedItem={activeStep}
        onChange={handleSlideChange}
        autoPlay
        infiniteLoop
        showThumbs={false}
        showStatus={false}
        swipeable
        emulateTouch
        renderArrowPrev={(onClickHandler, hasPrev, label) =>
          hasPrev && (
            <Button
              size="small"
              onClick={handleBack}
              sx={{ position: 'absolute', left: 10, top: '50%', transform: 'translateY(-50%)', bgcolor: 'white' }}
            >
              {theme.direction === 'rtl' ? <KeyboardArrowRight /> : <KeyboardArrowLeft />}
            </Button>
          )
        }
        renderArrowNext={(onClickHandler, hasNext, label) =>
          hasNext && (
            <Button
              size="small"
              onClick={handleNext}
              sx={{ position: 'absolute', right: 10, top: '50%', transform: 'translateY(-50%)', bgcolor: 'white' }}
            >
              {theme.direction === 'rtl' ? <KeyboardArrowLeft /> : <KeyboardArrowRight />}
            </Button>
          )
        }
      >
        {images.map((item) => (
          <Box key={item.label}>
            <Box
              component="img"
              sx={{
                height: 255,
                display: 'block',
                maxWidth: 400,
                overflow: 'hidden',
                width: '100%',
              }}
              src={item.imgPath}
              alt={item.label}
            />
          </Box>
        ))}
      </Carousel>

      <MobileStepper
        steps={maxSteps}
        position="static"
        activeStep={activeStep}
        nextButton={
          <Button
            size="small"
            onClick={handleNext}
            disabled={activeStep === maxSteps - 1}
          >
            Next
            {theme.direction === 'rtl' ? <KeyboardArrowLeft /> : <KeyboardArrowRight />}
          </Button>
        }
        backButton={
          <Button size="small" onClick={handleBack} disabled={activeStep === 0}>
            {theme.direction === 'rtl' ? <KeyboardArrowRight /> : <KeyboardArrowLeft />}
            Back
          </Button>
        }
      />
    </Box>
  );
}

export default SwipeableTextMobileStepper;

方案2:使用MUI Base的Swipeable组件(官方原生支持)

MUI Base提供的底层Swipeable组件完全兼容React18,可自定义实现轮播逻辑,更贴合Material UI生态:

  1. 安装依赖:
npm install @mui/base
  1. 基于Swipeable组件重构轮播逻辑,保留原有MobileStepper等Material UI组件的使用。

方案3:自行实现滑动逻辑(无第三方依赖)

通过React的useRef监听触摸/鼠标事件,计算滑动距离实现切换:

  • 监听touchstart/mousedown记录起始位置
  • 监听touchmove/mousemove计算位移
  • 监听touchend/mouseup判断是否触发轮播项切换

关键说明

  • 方案1最快捷,无需大量重构代码,完整保留原有功能
  • 方案2更贴合MUI生态,适合需要高度自定义的场景
  • 方案3无外部依赖,适合轻量需求场景

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 00:40:10