在 React with SCSS 中添加 div 淡出和 div 的条件渲染
Add div fade-out in React with SCSS and conditional rendering of div
我目前使用 SCSS/SASS mixin
和 keyframes
.
在 React 中成功淡入有条件渲染的 div
我还想在 div
关闭后添加淡出功能。我尝试动态更改 div (className={div_enable?"div_in":"div_out"}
) 的 class,但问题是,将条件渲染更改为 false
/关闭 div
的事件](在我下面的示例中,当 div
处于焦点时按 Enter
)是将其 class 更改为 div_out
的相同操作。条件渲染首先被触发,因此 div
在可以应用淡出 div_out
class 之前完全消失。
如何在 div
关闭时添加淡出功能的同时保留 div 的条件渲染逻辑?
Update:我发现了 using OnAnimationEnd
的可能性,我认为这是最容易实现的,无需大修我的代码。但是,我不确定如何将教程的功能组件代码转换为我项目的 Class 组件代码。
我也发现了using ReactCSSTransitionGroup
的可能性。链接的教程使用了一个 React Class 组件,我正在慢慢地尝试去除它并将其转录到我下面的代码中。但是,恐怕将 ReactCSSTransitionGroup
实施到我的实际项目中(此处未显示)将需要进行大修,因此我更愿意使用 OnAnimationEnd
之类的东西。
CodePen with working SCSS/fade-in
class MyForm extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
this.state = { div_enable: false };
}
submitForm = (event) => {
event.preventDefault();
this.setState({ div_enable: true }, () => this.myRef.current.focus());
};
closeModal = () => {
if (event.key === "Enter" && event.shiftKey === false) {
this.setState({ div_enable: false });
}
};
render() {
const { div_enable } = this.state;
return (
<div content>
<form onSubmit={this.submitForm}>
<input
id="text_entry"
type="text"
placeholder="Enter text"
/>
<input type="submit" />
</form>
{div_enable && (
<div
className={div_enable?"div_in":"div_out"}
onKeyDown={this.closeModal}
tabIndex={0}
ref={this.myRef}
>
<p>Press Enter to make me disappear.{" "}
</p>
</div>
)}
</div>
);
}
}
ReactDOM.render(<MyForm />, document.getElementById("root"));
@mixin fade-in {
opacity: 1;
animation-name: fadeInOpacity;
animation-iteration-count: 1;
animation-timing-function: ease-in;
animation-duration: 0.2s;
}
@mixin fade-out {
opacity: 0;
animation-name: fadeInOpacity;
animation-iteration-count: 1;
animation-timing-function: ease-in;
animation-duration: 0.2s;
}
@keyframes fadeInOpacity {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.div_in {
@include fade-in;
border: 1px solid;
background: lightblue;
}
.div_out {
@include fade-out;
border: 1px solid;
background: lightblue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="root"></div>
如果您想为条件渲染元素启用 CSS 退出动画,您可以完全删除 SCSS 并转换条件渲染声明(例如,{my_condition && ... }
) 到 <
CSSTransition
>
tags--while making sure to include the unmountOnExit
prop within the tags (which prop is inherited from CSSTransition
's parent component, Transition
)--像这样:
旧:
// Javascript
{div_enable &&
<div className={div_enable?"div_in":"div_out"}>
<p>My paragraph</p>
</div>
}
// CSS
/* [See original question] */
新:
// Javascript
{
<CSSTransition
in={div_enable}
timeout={200}
classNames="fade"
unmountOnExit
>
<div className="div_in">
<p>My paragraph</p>
</div>
</CSSTransition>
}
// CSS
.div_in {
border: 1px solid;
background: lightblue;
}
.fade-enter {
opacity: 0;
}
.fade-enter-active {
opacity: 1;
transition: opacity 200ms;
}
.fade-exit {
opacity: 1;
}
.fade-exit-active {
opacity: 0;
transition: opacity 200ms;
}
完整代码(我无法让 importing ES6 modules ({CSSTransition}
) in Whosebug's editor 工作,所以下面的 Whosebug 代码没有 运行):
import {CSSTransition} from "https://cdnjs.cloudflare.com/ajax/libs/react-transition-group/4.4.1/react-transition-group.min.js";
class MyForm extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
this.state = {
text_exists_enable: false,
text_empty_enable: false,
text_field: "",
};
}
textEntered = (event) => {
this.setState({ text_field: event.target.value });
console.log(event.target.value);
};
submitForm = (event) => {
event.preventDefault();
if (this.state.text_field !== "") {
this.setState(
{
text_exists_enable: true,
},
() => this.myRef.current.focus()
);
} else {
this.setState(
{
text_empty_enable: true,
},
() => this.myRef.current.focus()
);
}
};
closeBlueBox = () => {
if (event.key === "Enter" && event.shiftKey === false) {
this.setState({
text_exists_enable: false,
text_empty_enable: false,
});
}
};
render() {
const { text_exists_enable, text_empty_enable } = this.state;
return (
<div content>
<form onSubmit={this.submitForm}>
<input
type="text"
placeholder="Enter text"
onChange={this.textEntered}
/>
<input type="submit" />
</form>
{
<CSSTransition
in={text_exists_enable}
timeout={200}
classNames="fade"
unmountOnExit
>
<div
className="div_in"
onKeyDown={this.closeBlueBox}
tabIndex={0}
ref={this.myRef}
>
<p> Textbox HAS text! </p>
</div>
</CSSTransition>
}
{
<CSSTransition
in={text_empty_enable}
timeout={200}
classNames="fade"
unmountOnExit
>
<div
className="div_in"
onKeyDown={this.closeBlueBox}
tabIndex={0}
ref={this.myRef}
>
<p> Textbox is EMPTY! </p>
</div>
</CSSTransition>
}
</div>
);
}
}
ReactDOM.render(<MyForm />, document.getElementById("root"));
.div_in {
border: 1px solid;
background: lightblue;
}
.fade-enter {
opacity: 0;
}
.fade-enter-active {
opacity: 1;
transition: opacity 200ms;
}
.fade-exit {
opacity: 1;
}
.fade-exit-active {
opacity: 0;
transition: opacity 200ms;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-transition-group/4.4.1/react-transition-group.min.js"></script>
<div id="root"></div>
我目前使用 SCSS/SASS mixin
和 keyframes
.
div
我还想在 div
关闭后添加淡出功能。我尝试动态更改 div (className={div_enable?"div_in":"div_out"}
) 的 class,但问题是,将条件渲染更改为 false
/关闭 div
的事件](在我下面的示例中,当 div
处于焦点时按 Enter
)是将其 class 更改为 div_out
的相同操作。条件渲染首先被触发,因此 div
在可以应用淡出 div_out
class 之前完全消失。
如何在 div
关闭时添加淡出功能的同时保留 div 的条件渲染逻辑?
Update:我发现了 using OnAnimationEnd
的可能性,我认为这是最容易实现的,无需大修我的代码。但是,我不确定如何将教程的功能组件代码转换为我项目的 Class 组件代码。
我也发现了using ReactCSSTransitionGroup
的可能性。链接的教程使用了一个 React Class 组件,我正在慢慢地尝试去除它并将其转录到我下面的代码中。但是,恐怕将 ReactCSSTransitionGroup
实施到我的实际项目中(此处未显示)将需要进行大修,因此我更愿意使用 OnAnimationEnd
之类的东西。
CodePen with working SCSS/fade-in
class MyForm extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
this.state = { div_enable: false };
}
submitForm = (event) => {
event.preventDefault();
this.setState({ div_enable: true }, () => this.myRef.current.focus());
};
closeModal = () => {
if (event.key === "Enter" && event.shiftKey === false) {
this.setState({ div_enable: false });
}
};
render() {
const { div_enable } = this.state;
return (
<div content>
<form onSubmit={this.submitForm}>
<input
id="text_entry"
type="text"
placeholder="Enter text"
/>
<input type="submit" />
</form>
{div_enable && (
<div
className={div_enable?"div_in":"div_out"}
onKeyDown={this.closeModal}
tabIndex={0}
ref={this.myRef}
>
<p>Press Enter to make me disappear.{" "}
</p>
</div>
)}
</div>
);
}
}
ReactDOM.render(<MyForm />, document.getElementById("root"));
@mixin fade-in {
opacity: 1;
animation-name: fadeInOpacity;
animation-iteration-count: 1;
animation-timing-function: ease-in;
animation-duration: 0.2s;
}
@mixin fade-out {
opacity: 0;
animation-name: fadeInOpacity;
animation-iteration-count: 1;
animation-timing-function: ease-in;
animation-duration: 0.2s;
}
@keyframes fadeInOpacity {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.div_in {
@include fade-in;
border: 1px solid;
background: lightblue;
}
.div_out {
@include fade-out;
border: 1px solid;
background: lightblue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="root"></div>
如果您想为条件渲染元素启用 CSS 退出动画,您可以完全删除 SCSS 并转换条件渲染声明(例如,{my_condition && ... }
) 到 <
CSSTransition
>
tags--while making sure to include the unmountOnExit
prop within the tags (which prop is inherited from CSSTransition
's parent component, Transition
)--像这样:
旧:
// Javascript
{div_enable &&
<div className={div_enable?"div_in":"div_out"}>
<p>My paragraph</p>
</div>
}
// CSS
/* [See original question] */
新:
// Javascript
{
<CSSTransition
in={div_enable}
timeout={200}
classNames="fade"
unmountOnExit
>
<div className="div_in">
<p>My paragraph</p>
</div>
</CSSTransition>
}
// CSS
.div_in {
border: 1px solid;
background: lightblue;
}
.fade-enter {
opacity: 0;
}
.fade-enter-active {
opacity: 1;
transition: opacity 200ms;
}
.fade-exit {
opacity: 1;
}
.fade-exit-active {
opacity: 0;
transition: opacity 200ms;
}
完整代码(我无法让 importing ES6 modules ({CSSTransition}
) in Whosebug's editor 工作,所以下面的 Whosebug 代码没有 运行):
import {CSSTransition} from "https://cdnjs.cloudflare.com/ajax/libs/react-transition-group/4.4.1/react-transition-group.min.js";
class MyForm extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
this.state = {
text_exists_enable: false,
text_empty_enable: false,
text_field: "",
};
}
textEntered = (event) => {
this.setState({ text_field: event.target.value });
console.log(event.target.value);
};
submitForm = (event) => {
event.preventDefault();
if (this.state.text_field !== "") {
this.setState(
{
text_exists_enable: true,
},
() => this.myRef.current.focus()
);
} else {
this.setState(
{
text_empty_enable: true,
},
() => this.myRef.current.focus()
);
}
};
closeBlueBox = () => {
if (event.key === "Enter" && event.shiftKey === false) {
this.setState({
text_exists_enable: false,
text_empty_enable: false,
});
}
};
render() {
const { text_exists_enable, text_empty_enable } = this.state;
return (
<div content>
<form onSubmit={this.submitForm}>
<input
type="text"
placeholder="Enter text"
onChange={this.textEntered}
/>
<input type="submit" />
</form>
{
<CSSTransition
in={text_exists_enable}
timeout={200}
classNames="fade"
unmountOnExit
>
<div
className="div_in"
onKeyDown={this.closeBlueBox}
tabIndex={0}
ref={this.myRef}
>
<p> Textbox HAS text! </p>
</div>
</CSSTransition>
}
{
<CSSTransition
in={text_empty_enable}
timeout={200}
classNames="fade"
unmountOnExit
>
<div
className="div_in"
onKeyDown={this.closeBlueBox}
tabIndex={0}
ref={this.myRef}
>
<p> Textbox is EMPTY! </p>
</div>
</CSSTransition>
}
</div>
);
}
}
ReactDOM.render(<MyForm />, document.getElementById("root"));
.div_in {
border: 1px solid;
background: lightblue;
}
.fade-enter {
opacity: 0;
}
.fade-enter-active {
opacity: 1;
transition: opacity 200ms;
}
.fade-exit {
opacity: 1;
}
.fade-exit-active {
opacity: 0;
transition: opacity 200ms;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-transition-group/4.4.1/react-transition-group.min.js"></script>
<div id="root"></div>