Search code examples
reactjsecmascript-6timeoutes6-promise

Return multiple values over time in ES6 & React


Okay, so is there a way to return a value from a function - the way return does - but not stop the function - the way return does?

I need this so I can keep returning values every so often.

My code looks like:

loopingTitleTextHandler = () => {
    const title = ["good", "cool", "887H", "Vertical"];
    for (i = 0; i < 999999; i++) {
        var j = i%4;
        // loopingTitleTextHandler() // calls itself before return terminates execution 
        return title[j]; //return 0,1,2,3 in a loop with 3 second delay
    }
}

My React Component

<ShowTitle size={230}
    title={this.loopingTitleTextHandler()}
    color="#FDA7DC" />

Edit: I'm after a solution that solves this problem in the function like this python answer: Return multiple values over time but using ES6.

import time

def myFunction(limit):
    for i in range(0,limit):
        time.sleep(2)
        yield i*i

for x in myFunction(100):
    print( x )

Solution

  • In the context of React, I think it would make more sense to manage these values through state. Assuming you want to return one new title every 3 seconds, you can do the following:

    Here's a sandbox: https://codesandbox.io/s/elated-rgb-n4j6z

    App.js

    import React from "react";
    import ReactDOM from "react-dom";
    import ShowTitle from "./ShowTitle";
    
    import "./styles.css";
    
    class App extends React.Component {
      state = {
        title: ["good", "cool", "887H", "Vertical"],
        currentTitle: "good"
      };
    
      loopingTitleTextHandler = () => {
        const { currentTitle, title } = this.state;
        const nextTitleIndex =
          title.indexOf(currentTitle) + 1 === title.length
            ? 0
            : title.indexOf(currentTitle) + 1;
    
        this.setState({ currentTitle: title[nextTitleIndex] });
      };
      render() {
        return (
          <div className="App">
            <ShowTitle
              changeTitle={this.loopingTitleTextHandler}
              currentTitle={this.state.currentTitle}
            />
          </div>
        );
      }
    }
    
    const rootElement = document.getElementById("root");
    ReactDOM.render(<App />, rootElement);
    

    ShowTitle.js

    import React from "react";
    
    class ShowTitle extends React.Component {
      componentDidMount() {
        setInterval(() => {
          this.props.changeTitle();
          console.log(this.props.currentTitle + " " + new Date().getTime());
        }, 3000);
      }
    
      render() {
        return <div>Title: {this.props.currentTitle}</div>;
      }
    }
    
    export default ShowTitle;
    

    In the parent component (App.js) we keep track of the currentTitle. When loopingTitleTextHandler() is called, we update our state.currentTitle with the next title in the array. currentTitle gets passed down to ShowTitle component.

    In Child component, we use a setInterval() to call loopingTitleTextHandler() every 3 seconds, and display the next title.