Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modify React Elements in ES6 using a for loop and setTimeout

I am trying to create a typewriter animation like this in my es6 component (essentially, iteratively renders additional passed elements or letters). However, any time I execute / render this component, all that is rendered is the first element / letter, 'a', of the larger set, 'abc'. The timeout period is working fine, so I think that the for loop is failing. How do I properly run a for loop over a setTimeout function in es6 such that my new elements will render? Thanks.

import React from 'react';
import { CSSTransitionGroup } from 'react-transition-group';
import Radium from 'radium';

export default class Logo extends React.Component {
  constructor(props) {
    super();
    this.state = {
      final: ''
    }
    this.typeWriter = this.typeWriter.bind(this);
  }

  typeWriter(text, n) {
    if (n < (text.length)) {
      let k = text.substring(0, n+1);
      this.setState({ final: k });
      n++;
      setTimeout( () => { this.typeWriter(text, n) }, 1000 );
    }
  }

  render() {
    this.typeWriter('abc', 0);
    return (
      <div>
        <h1>{this.state.final}</h1>
      </div>
    );
  }
}

module.exports = Radium(Logo);
like image 905
Jimmy Avatar asked Feb 24 '26 14:02

Jimmy


1 Answers

Since this.typeWriter('abc', 0); is in the render function, whenever the state changes, it runs the typewriter method, which updates the state back to a.

Move the this.typeWriter('abc', 0); to componentDidMount(). It will start the type writer when the component has finished rendering.

class Logo extends React.Component {
  constructor(props) {
    super();
    this.state = {
      final: ''
    }
    this.typeWriter = this.typeWriter.bind(this);
  }

  typeWriter(text, n) {
    if (n < (text.length)) {
      let k = text.substring(0, n+1);
      this.setState({ final: k });
      n++;
      setTimeout( () => { this.typeWriter(text, n) }, 1000 );
    }
  }
  
  componentDidMount() {
    this.typeWriter('abc', 0);
  }

  render() {
    return (
      <div>
        <h1>{this.state.final}</h1>
      </div>
    );
  }
}

ReactDOM.render(
  <Logo />,
  demo
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="demo"></div>
like image 176
Ori Drori Avatar answered Feb 27 '26 03:02

Ori Drori



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!