首页 > 解决方案 > 使用 SCSS 在 React 中添加 div 淡出和 div 的条件渲染

问题描述

我目前div使用 SCSS/SASSmixinkeyframes.

我还想div在它关闭后添加淡出功能。我尝试动态更改 div ( className={div_enable?"div_in":"div_out"}) 的类,但问题是,将条件渲染更改为false/dismisses 的事件(在下面的示例中,当焦点处于焦点时div按下)与将其类更改为的相同操作. 条件渲染首先被触发,因此在应用淡出类之前完全消失。Enterdivdiv_outdivdiv_out

如何在 divdiv被关闭时添加淡出功能时保留 div 的条件渲染逻辑?

更新:我发现了使用OnAnimationEnd的可能性,我认为这将是最容易实现的,而无需彻底检查我的代码。但是,我不确定如何将教程的功能组件代码转换为我项目的类组件代码。

我还发现了使用ReactCSSTransitionGroup. 链接的教程使用了一个 React 类组件,我正在慢慢尝试对其进行修改并将其转录为下面的代码。但是,我担心ReactCSSTransitionGroup在我的实际项目中实施(这里没有看到)需要进行相当大的检修,所以我宁愿得到类似OnAnimationEnd工作的东西。

带有工作 SCSS/淡入的 CodePen

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>

标签: javascriptreactjssassscss-mixins

解决方案


如果你想为你的条件渲染元素启用 CSS 退出动画,你可以完全移除 SCSS 并将你的条件渲染声明(例如,{my_condition && ... })转换为标签——同时确保在标签中包含道具(哪个道具是继承自的父组件,)——就像这样:<CSSTransition>unmountOnExitCSSTransitionTransition

// 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;
}

完整代码(我无法在 StackOverflow 的编辑器中导入 ES6 模块({CSSTransition} ) ,因此下面的 StackOverflow 代码无法运行):

工作 CodePen 示例

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>


推荐阅读