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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 15:55:04