1

I was working with Single-Page App on React, and I got a problem with function so it takes some time to return the results and render it. With that I want to ask if I can change it as asynchronous function to get the result after it returns, but other components would not stuck as well.

I may misunderstand how it should work but here is the basic example of my problem:

class Example extends React.Component {

  state = {
    data: "whatever"
  }

  myHeavyFunction(data){
    //while this function works whole page on browser freezes for 3-5 second
    return (<div>{result}</div>);
  }

  buttonClicked(){
    this.setState({data: "new whatever"});
  }

  render(){
    return(
      <div>{this.myHeavyFunction(this.state.data)}</div>
    );
  }

}

I didn't use any API request, it's just a function which works with big data. In my case "myHeavyFunction" is a different component and I've tried to use React.lazy/Suspense but unfortunately it loads only when you refresh the page.

So I want the function which renders asynchronously with loading spinner after I click the button so the page doesn't refreshes and other components wouldn't freeze.

1 Answer 1

1

You can convert myHeavyFunction to return a Promise and within any handler you can either use a Promise-chain, or make the handler an async function and await the return value. Couple this with some "loading" state and you can display a loading indicator.

class Example extends Component {
  state = {
    data: "whatever",
    loading: false, // <-- loading state
  };

  myHeavyFunction = () => {
    return new Promise(resolve => {
      setTimeout(() => resolve("new whatever"), 5000); // <-- "expensive cmoputation"
    });
  };

  buttonClicked = async () => { // <-- async function
    this.setState({
      loading: true // <-- loading true
    });
    const data = await this.myHeavyFunction(); // await expensive computation
    this.setState({
      data,
      loading: false // <-- loading false
    });
  };

  render() {
    const { data, loading } = this.state;
    return (
      <div>
        <div>{loading ? "loading..." : data}</div> // <-- conditional render
        <button onClick={this.buttonClicked}>Update</button>
      </div>
    );
  }
}

Edit Async UI

Sign up to request clarification or add additional context in comments.

5 Comments

I agree with the loading indidcator part. For the second part, is it because making it return a promise takes it off the event loop, making it not to block it?
@Selçuk Basically, yes. It offloads it from the main thread and thus doesn't block it.
But is not JavaScript single threaded. The thread you mean is somehow different, right? Does it mean just off the event loop?
@Selçuk JS is single threaded, yes, but this places code/callbacks/etc into the queue that is processed by the event loop so it is non-blocking.
Thanks a lot, it sounds like the event loop is actually apart from the js thread, gonna need to read about it more.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.