[英]Animation on unmount with React and react-transition-group
我正在使用 React,我正在嘗試使用 React-transition-group 創建一個Fade
組件,以根據狀態中存儲的條件淡入和淡出元素: http ://reactcommunity.org/react-transition -組/css-過渡/
這就是我現在所擁有的:
import React from "react";
import ReactDOM from "react-dom";
import { CSSTransition } from "react-transition-group";
import "./styles.css";
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
mounted: false
};
}
componentDidMount() {
setTimeout(() => {
this.setState({
mounted: true
});
}, 10);
}
render() {
return (
<div className="root">
<CSSTransition
in={this.state.mounted}
appear={true}
unmountOnExit
classNames="fade"
timeout={1000}
>
{this.state.mounted ? (
<div>
<button
onClick={() => {
this.setState({
mounted: !this.state.mounted
});
}}
>
Remove
</button>
<div>COMPONENT</div>
</div>
) : (
<div />
)}
</CSSTransition>
</div>
);
}
}
這是CSS
.fade-enter {
opacity: 0;
transition: opacity .5s ease;
}
.fade-enter-active {
opacity: 1;
transition: opacity .5s ease;
}
.fade-exit {
opacity: 1;
transition: opacity .5s ease;
}
.fade-exit-active {
opacity: 0;
transition: opacity .5s ease;
}
安裝組件后,不透明度會在 0.5 秒內從 0 過渡到 1。 但是當它卸載時,它沒有動畫:組件在沒有過渡的情況下消失。
我用這個組件制作了一個沙箱來測試它: https ://codesandbox.io/s/k027m33y23 我確信這是一種常見的情況,但我找不到在卸載時為組件設置動畫的方法。 如果有人有任何想法,將非常歡迎!
-- 編輯 -- 正如@IPutuYogaPermana 所說,CSSTransition 中的條件渲染不是必需的。 所以這:
{this.state.mounted ? (
<div>
<button
onClick={() => {
this.setState({
mounted: !this.state.mounted
});
}}
>
Remove
</button>
<div>COMPONENT</div>
</div>
) : (
<div />
)}
應該是這樣的:
<div>
<button
onClick={() => {
this.setState({
mounted: !this.state.mounted
});
}}
>
Remove
</button>
<div>COMPONENT</div>
</div>
該組件將根據 CSSTransition 組件中的in
屬性自動掛載或卸載。 這里是codesandbox中的最終代碼: https ://codesandbox.io/s/62m86nm7qw
這是預期的,因為隨着狀態的改變,動畫還沒有開始,但孩子們已經走了。
所以它就像神奇的瞬間消失。 那么我們只需要隱藏它吧? 刪除條件渲染。
我檢查過,動畫完成后節點自動刪除。 所以不需要使用條件渲染。 幸運的是! 代碼變成:
import React from "react";
import ReactDOM from "react-dom";
import { CSSTransition } from "react-transition-group";
import "./styles.css";
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
logoIntro: true,
mounted: false
};
}
componentDidMount() {
this.setState({
mounted: true
});
}
render() {
return (
<div className="root">
<CSSTransition
in={this.state.mounted}
appear={true}
unmountOnExit
classNames="fade"
timeout={1000}
>
<div>
<button
onClick={() => {
this.setState({
mounted: !this.state.mounted
});
}}
>
Remove
</button>
<div>SOME COMPONENT</div>
</div>
</CSSTransition>
</div>
);
}
}
ReactDOM.render(<Example />, document.getElementById("root"));
我創建了一個通用的WrapperComponent
,這樣您就可以對元素進行動畫處理,而不必總是一遍又一遍地編寫相同的東西。
import { useEffect, useState } from "react"
import { CSSTransition } from "react-transition-group"
export const MountAnimation = ({
children,
timeout = 300, // MATCH YOUR DEFAULT ANIMATION DURATION
isVisible = false,
unmountOnExit = true,
classNames = "transition-translate-y", // ADD YOUR DEFAULT ANIMATION
...restProps
}) => {
const [isMounted, setIsMounted] = useState(isVisible)
useEffect(() => setIsMounted(isVisible), [isVisible])
return (
<CSSTransition
in={isMounted}
timeout={timeout}
classNames={classNames}
unmountOnExit={unmountOnExit}
{...restProps}
>
<>{children}</>
</CSSTransition>
)
}
就像這樣使用它:
import { MountAnimation } from '../../path/to/component'
...
const [isElementVisible, setIsElementVisible] = useState(false)
return (
<MountAnimation isVisible={isElementVisible}>
// your content here
</MountAnimation>
)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.