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)}传递事件均无效,期望点击分页的「>」「<」按钮或页码时,能切换页面并展示对应卡片。
原因分析
- Material UI的Pagination组件onChange事件的第一个参数类型并非
React.ChangeEvent<MouseEvent>,而是React.MouseEvent,类型不匹配导致报错。 - 手动包装onChange时传递了旧的
page状态值,而非点击后的新页码,导致分页逻辑失效。 - 渲染时直接使用原始数据而非分页后的
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
相关产品推荐
相关产品推荐

