如何在React中再次加载相同的组件?

时间:2019-12-20 19:06:51

标签: javascript reactjs

我正在尝试重新加载我的main.js组件,但是第一次加载时它仅加载一次。

当第一次加载组件时,我的文本动画效果很好,但是当我访问不同的路线并再次访问该组件时,文本动画会停止。

class Main extends Component {

    typeWriter() {
        var TxtRotate = function (el, toRotate, period) {
            this.toRotate = toRotate;
            this.el = el;
            this.loopNum = 0;
            this.period = parseInt(period, 10) || 2000;
            this.txt = '';
            this.tick();
            this.isDeleting = false;
        };

        TxtRotate.prototype.tick = function () {
            var i = this.loopNum % this.toRotate.length;
            var fullTxt = this.toRotate[i];

            if (this.isDeleting) {
                this.txt = fullTxt.substring(0, this.txt.length - 1);
            } else {
                this.txt = fullTxt.substring(0, this.txt.length + 1);
            }

            this.el.innerHTML = '<span class="wrap">' + this.txt + '</span>';

            var that = this;
            var delta = 300 - Math.random() * 100;

            if (this.isDeleting) { delta /= 2; }

            if (!this.isDeleting && this.txt === fullTxt) {
                delta = this.period;
                this.isDeleting = true;
            } else if (this.isDeleting && this.txt === '') {
                this.isDeleting = false;
                this.loopNum++;
                delta = 500;
            }

            setTimeout(function () {
                that.tick();
            }, delta);
        };

        window.onload = function () {
            var elements = document.getElementsByClassName('txt-rotate');
            for (var i = 0; i < elements.length; i++) {
                var toRotate = elements[i].getAttribute('data-rotate');
                var period = elements[i].getAttribute('data-period');
                if (toRotate) {
                    new TxtRotate(elements[i], JSON.parse(toRotate), period);
                }
            }
            // INJECT CSS
            var css = document.createElement("style");
            css.type = "text/css";
            css.innerHTML = ".txt-rotate > .wrap { border-right: 0.08em solid #666 }";
            document.body.appendChild(css);
        };
    }

    componentDidMount() {
        this.typeWriter();
    }



    render() {
        return (
            <div id="main" >
                    <h2 id="typeWrite" className="mt-4 mb-5">I'm a
                     <span className="txt-rotate" data-period="2000" data-rotate='[ " Developer.", " Programmer."]'></span>
                    </h2>
            </div>
        )
    }
}

export default Main;

如何使其重新加载此组件加载?

1 个答案:

答案 0 :(得分:2)

使用React有状态组件来呈现类型编写器效果,不要像使用typeWriter()方法那样尝试“突破” React。我在下面使用功能组件和React钩子编写了一个功能齐全的演示:

const { useRef, useState, useReducer, useMemo, useEffect } = React;

const typeWriterInitialState = {
  index: 0,
  deleting: false,
  length: 0
};

const typeWriterReducer = (state, action) => {
  const { index, deleting, length } = state;
  const { text, fullText } = action;

  if (deleting && text === '') return {
    index: index + 1,
    deleting: false,
    length: length + 1
  };

  if (!deleting && text === fullText) return {
    index: index,
    deleting: true,
    length: length - 1
  };

  return {
    index,
    deleting,
    length: length + (deleting ? -1 : 1)
  };
};

function useTypeWriter (props) {
  const ref = useRef(null);
  const [period] = useState(props.period || 2000);
  const [rotate] = useState(props.rotate);
  const [state, update] = useReducer(
    typeWriterReducer,
    typeWriterInitialState
  );
  const { index, deleting, length } = state;
  const fullText = rotate[index % rotate.length];
  const text = fullText.substring(0, length);
  const delta = useMemo(() => {
    if (text === fullText && !deleting) return period;
    if (text === '' && deleting) return 500;
    return (200 * Math.random() + 100) * (deleting ? 0.5 : 1);
  }, [text, fullText, deleting, period]);

  useEffect(() => {
    ref.current.textContent = text;

    const timeout = setTimeout(update, delta, { text, fullText });

    return () => {
      clearTimeout(timeout);
    };
  }, [ref, delta, text, fullText, update]);

  return ref;
}

const wrapStyle = { borderRight: '0.08em solid #666' };

function TypeWriter (props) {
  const { period, rotate } = props;
  const wrapEl = useTypeWriter({ period, rotate });

  return (
    <span ref={wrapEl} style={wrapStyle}/>
  );
}

const mainRotate = ['Developer.', 'Programmer.'];

function Main () {
  return (
    <div>
      <h2>I'm a <TypeWriter period={2000} rotate={mainRotate}/></h2>
    </div>
  );
}

ReactDOM.render(<Main/>, document.body);
h2 {
  white-space: pre-wrap;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>