如何在React中将MUI过渡组件属性传递给子组件?
问题描述
我有一个带按钮的父组件,点击按钮会打开子组件的MUI Snackbar。老师要求为点击事件添加滑动过渡效果,使Snackbar显示时带有滑动动画。我参考MUI官方文档的Slide过渡代码尝试实现,但不知道如何将过渡属性正确传递给子组件,在TransitionComponent={transition}处出现报错。以下是父组件和子组件的代码,求解决建议:
父组件代码
//NOTE: transition type TransitionProps = Omit<SlideProps, 'direction'>; const TransitionLeft = (props: TransitionProps) => <Slide {...props} direction="left" />; export const Messages = () => { const [msgStatus, setMsgStatus] = useState(""); //NOTE: transition const [transition, setTransition] = useState<React.ComponentType<TransitionProps> | undefined>(undefined); const handleClick = (Transition: React.ComponentType<TransitionProps>) => () => { setTransition(() => Transition); setMsgStatus('info'); }; return ( <Stack> <Button onClick={handleClick(TransitionLeft)} > open info </Button> <InfoMessage open={msgStatus === 'info'} transition={transition} onClose={() => setMsgStatus('')} /> </Stack> ) }
子组件代码
interface InfoMessageProps { open: boolean; onClose: () => void; transition: React.ElementType; } export const InfoMessage = ({ open, onClose, transition }: InfoMessageProps) => { const handleClose = (): void => { onClose(); }; return ( <Snackbar open={open} autoHideDuration={4000} anchorOrigin={{ vertical: 'top', horizontal: 'right' }} onClose={handleClose} TransitionComponent={transition} // 此处报错 > <Alert sx={{ width: '487px', height: '104px', paddingTop: '20px', paddingLeft: '20px', backgroundColor: '#FDFDFD', }} icon={false} action={( <IconButton aria-label="close" color="inherit" size="small" > <CloseIcon style={{ fontSize:'24px' }} /> </IconButton> )} onClose={handleClose} > <AlertTitle sx={{ paddingRight:'80px' }}> <Typography variant='headings.h4'>title</Typography> </AlertTitle> <Typography variant='captions.default'>Insert message here</Typography> </Alert> </Snackbar> ); };
解决建议
1. 统一类型定义
报错核心原因是父子组件的transition类型不匹配:父组件中transition的类型是React.ComponentType<TransitionProps> | undefined,但子组件Props里定义为React.ElementType,导致TS类型校验失败。
修改子组件的类型定义,确保和父组件一致:
import { SlideProps } from '@mui/material/Slide'; type TransitionProps = Omit<SlideProps, 'direction'>; interface InfoMessageProps { open: boolean; onClose: () => void; transition?: React.ComponentType<TransitionProps>; // 标记为可选,匹配父组件初始undefined值 }
2. 处理TransitionComponent的默认值
Snackbar的TransitionComponent不接受undefined,可以给子组件的transition设置默认过渡组件(比如MUI内置的Fade),避免初始值问题:
import { Fade } from '@mui/material'; // ... return ( <Snackbar open={open} autoHideDuration={4000} anchorOrigin={{ vertical: 'top', horizontal: 'right' }} onClose={handleClose} TransitionComponent={transition ?? Fade} // 空值合并运算符提供默认值 > {/* Alert内容保持不变 */} </Snackbar> );
3. 优化父组件状态逻辑(可选)
如果只需要固定使用TransitionLeft过渡,完全不需要维护transition状态,直接把组件作为props传给子组件即可,代码更简洁:
export const Messages = () => { const [msgStatus, setMsgStatus] = useState(""); return ( <Stack> <Button onClick={() => setMsgStatus('info')} > open info </Button> <InfoMessage open={msgStatus === 'info'} transition={TransitionLeft} // 直接传组件,无需状态 onClose={() => setMsgStatus('')} /> </Stack> ) }
4. 确保类型导入正确
确认所有相关类型都已正确导入,避免TS找不到类型的错误:
import { useState } from 'react'; import { Stack, Button, Fade } from '@mui/material'; import { Slide, SlideProps } from '@mui/material/Slide';
内容的提问来源于stack exchange,提问作者mariadev
相关产品推荐
相关产品推荐

