React Transition组件内联过渡样式无法生效问题
问题根源
你的代码一共有5个直接导致效果异常的问题:
Transition组件属性名写错:你写的onMountEnter、onMountExit是不存在的无效属性,控制组件进入时挂载、退出后卸载的正确属性是mountOnEnter和unmountOnExit。属性失效直接导致模态框初始加载就被挂载渲染,不会等触发打开逻辑才出现。- 内联样式没有绑定到DOM:你给
Modal组件传入了style属性,但Modal组件的根div元素只绑定了className,完全没有接收挂载传入的style属性,你写的opacity、transition规则根本没有应用到模态框元素上,自然不会有过渡效果。 - 状态逻辑冲突:你给Modal传入的
modalState是外层瞬时更新的布尔值,用这个值切换modal-open/modal-close类名,会和Transition的渐进式状态变化冲突,直接打断过渡流程。 - 导入路径不规范:你从
react-transition-group/cjs/Transition导入组件属于引用包内部构建产物,会绕过组件的属性校验逻辑,导致你写错属性名时没有控制台报错/警告,增加排查成本。 - 体验逻辑问题:遮罩层Backdrop直接用
{modalOpen && ...}做瞬时条件渲染,关闭模态框时遮罩会直接消失,无法和模态框的淡出动画同步。
修正步骤
- 修正Transition组件的属性,替换为正确的
mountOnEnter、unmountOnExit,同时把导入路径改成标准导入:import { Transition } from "react-transition-group",timeout值和你写的过渡时长300ms保持一致即可。 - 修改Modal组件,把父组件传入的
style属性绑定到组件根div元素上,让过渡样式能真正生效;删除依赖外层瞬时modalOpen状态切换类名的冲突逻辑,如果需要类名对应过渡状态,可以把Transition返回的state传给Modal,基于state值绑定对应类名。 - 把Backdrop的渲染逻辑移到Transition的渲染函数内部,和Modal同步接收过渡状态控制opacity,不要单独用
modalOpen做条件渲染,保证遮罩和模态框的动画同步;同样给Backdrop组件加上style属性绑定逻辑。
修正后核心代码
App组件修正部分
import { Transition } from "react-transition-group"; // 其余导入保持不变 function App() { const [modalOpen, setModalOpen] = useState(false); const onOpenModalHandler = () => setModalOpen(true); const onCloseModalHandler = () => setModalOpen(false); return ( <div className={classes["App"]}> <h1>React Animations</h1> <Transition in={modalOpen} timeout={300} mountOnEnter unmountOnExit > {(state) => { const transitionStyle = { transition: `opacity 300ms ease-out`, opacity: state === "exiting" || state === "exited" ? 0 : 1, } return ( <> {ReactDOM.createPortal( <Modal closeModal={onCloseModalHandler} style={transitionStyle} />, document.getElementById("modal") )} {ReactDOM.createPortal( <Backdrop style={transitionStyle}/>, document.getElementById("backdrop") )} </> ) }} </Transition> <button className={"Button"} onClick={onOpenModalHandler}> Open Modal </button> <h3>Animating Lists</h3> <List /> </div> ); } export default App;
Modal组件修正部分
import classes from "./Modal.module.css"; const Modal = (props) => { const onCloseModalHandler = () => { props.closeModal(); }; return ( // 绑定传入的内联样式到根元素 <div className={classes.Modal} style={props.style}> <h1>A Modal</h1> <button className="Button" onClick={onCloseModalHandler}> Dismiss </button> </div> ); }; export default Modal;
注意:Backdrop组件需要做和Modal相同的修改,在根div上绑定
style={props.style},否则遮罩层的过渡效果不会生效。
内容的提问来源于stack exchange,提问作者Nijaz
相关产品推荐
相关产品推荐

