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

React+TypeScript解决ChangeEvent类型不匹配错误

Material UI Pagination组件TypeScript类型错误解决方法

问题描述

在App.tsx中使用Material UI的Pagination组件时,传递onChange事件出现如下类型错误:

Argument of type 'ChangeEvent' is not assignable to parameter of type 'ChangeEvent'. Type 'unknown' is not assignable to type 'MouseEvent'.

尝试直接绑定onChange={handleChange}、通过onChange={(e) => handleChange(e, page)}传递事件均无效,期望点击分页的「>」「<」按钮或页码时,能切换页面并展示对应卡片。

原因分析

  1. Material UI的Pagination组件onChange事件的第一个参数类型并非React.ChangeEvent<MouseEvent>,而是React.MouseEvent,类型不匹配导致报错。
  2. 手动包装onChange时传递了旧的page状态值,而非点击后的新页码,导致分页逻辑失效。
  3. 渲染时直接使用原始数据而非分页后的currentData,切换页码后页面内容无变化。

解决方案

1. 修正handleChange的事件参数类型

使用Material UI提供的PaginationProps['onChange']类型定义函数,或直接将事件参数类型改为React.MouseEvent:

import { PaginationProps } from "@mui/material";

// 方式1:使用MUI提供的类型
const handleChange: PaginationProps['onChange'] = (event, pageCurrent) => {
  setPage(pageCurrent);
  _DATA.jump(pageCurrent);
};

// 方式2:直接指定事件类型
const handleChange = (event: React.MouseEvent, pageCurrent: number) => {
  setPage(pageCurrent);
  _DATA.jump(pageCurrent);
};

2. 正确绑定onChange事件

直接将handleChange绑定到Pagination的onChange属性,组件会自动传递事件和新页码参数:

<Pagination
  count={count}
  size="large"
  page={page}
  variant="outlined"
  shape="rounded"
  onChange={handleChange}
/>

3. 使用分页后的数据渲染卡片

将渲染逻辑中的data.map改为_DATA.currentData.map,确保展示当前页的数据:

{_DATA.currentData.map((item, id) => {
  return (
    <Grid
      item
      xs={12}
      sm={6}
      md={4}
      lg={3}
      xl={2}
      sx={{
        display: "flex",
        justifyContent: "center",
        marginTop: "1rem"
      }}
      key={item.id} // 将key移到Grid组件上,符合React规范
    >
      <Card
        sx={{
          p: "1rem",
          boxShadow: 4,
          maxWidth: {
            xs: "250px",
            sm: "250px",
            md: "280px",
            lg: "300px",
            xl: "300px"
          }
        }}
      >
        {/* 卡片内容保持不变 */}
        <CardActionArea>
          <CardMedia component="img" height="140" image={item.img} />
          <CardContent>
            <Typography gutterBottom variant="h5" component="div">
              {item.title}
            </Typography>
            <Typography variant="body2" color="text.secondary">
              Lizards are a widespread group of squamate reptiles, with
              over 6,000 species, ranging across all continents except
              Antarctica
            </Typography>
          </CardContent>
        </CardActionArea>
        <CardActions>
          <Button size="small">Favorite</Button>
        </CardActions>
      </Card>
    </Grid>
  );
})}

完整修正后的App.tsx代码

import React, { useState } from "react";
import {
  Pagination,
  Box,
  Button,
  Card,
  CardActionArea,
  CardActions,
  CardContent,
  CardMedia,
  Grid,
  Typography,
  PaginationProps
} from "@mui/material";
import { usePagination } from "./UsePagination";
import { default as data } from "./DATA.json";

export default function App() {
  const [page, setPage] = useState(1);
  const PER_PAGE = 6;
  const count = Math.ceil(data.length / PER_PAGE);
  const _DATA = usePagination(data, PER_PAGE);
  
  const handleChange: PaginationProps['onChange'] = (event, pageCurrent) => {
    setPage(pageCurrent);
    _DATA.jump(pageCurrent);
  };

  return (
    <Box sx={{ flexGrow: 1, margin: "0 2rem" }}>
      <Pagination
        count={count}
        size="large"
        page={page}
        variant="outlined"
        shape="rounded"
        onChange={handleChange}
      />
      <Grid
        container
        justifyContent="center"
        spacing={{ xs: 8, sm: 8, md: 8, lg: 8, xl: 8 }}
        className="GRID1"
      >
        {_DATA.currentData.map((item, id) => {
          return (
            <Grid
              item
              xs={12}
              sm={6}
              md={4}
              lg={3}
              xl={2}
              sx={{
                display: "flex",
                justifyContent: "center",
                marginTop: "1rem"
              }}
              key={item.id}
            >
              <Card
                sx={{
                  p: "1rem",
                  boxShadow: 4,
                  maxWidth: {
                    xs: "250px",
                    sm: "250px",
                    md: "280px",
                    lg: "300px",
                    xl: "300px"
                  }
                }}
              >
                <CardActionArea>
                  <CardMedia component="img" height="140" image={item.img} />
                  <CardContent>
                    <Typography gutterBottom variant="h5" component="div">
                      {item.title}
                    </Typography>
                    <Typography variant="body2" color="text.secondary">
                      Lizards are a widespread group of squamate reptiles, with
                      over 6,000 species, ranging across all continents except
                      Antarctica
                    </Typography>
                  </CardContent>
                </CardActionArea>
                <CardActions>
                  <Button size="small">Favorite</Button>
                </CardActions>
              </Card>
            </Grid>
          );
        })}
      </Grid>
    </Box>
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 09:25:27