albertoivo
albertoivo

Reputation: 409

Call another code while array.map() is running

I have the following react code:

{myArray.map(arr => { 
    return ( <MyComponent title={arr.ttile} /> ) 
})}

I would like to call a Loading component while the map() is not completely finished. Is it possible to do that? If yes, how would I do that?

Upvotes: 2

Views: 522

Answers (3)

Tholle
Tholle

Reputation: 112787

If you are getting your data from an API, you might want to render the data as usual, but you can get the data in the componentDidMount hook instead, and e.g. keep an additional piece of state isLoading which you can use in the render method to decide if you should show a loading component.

Example

function getBooks() {
  return new Promise(resolve => {
    setTimeout(() => resolve([{ title: "foo" }, { title: "bar" }]), 1000);
  });
}

function MyComponent(props) {
  return <div> {props.title} </div>;
}

class App extends React.Component {
  state = { books: [], isLoading: true };

  componentDidMount() {
    getBooks().then(books => {
      this.setState({ books, isLoading: false });
    });
  }

  render() {
    const { isLoading, books } = this.state;

    if (isLoading) {
      return <div> Loading... </div>;
    }

    return (
      <div>
        {this.state.books.map(book => <MyComponent title={book.title} />)}
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
<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="root"></div>

Upvotes: 2

Enrikisimo Lopez Ramos
Enrikisimo Lopez Ramos

Reputation: 393

you can have a boolean in a state, and just before you start array map put boolean true and run another code o component render, and then when array maps end you put that state to false, for redux im using state fetch start, fetching, fetched, and then you can take the control of situation

Upvotes: 0

Adam Nathaniel Davis
Adam Nathaniel Davis

Reputation: 425

If you want to actually be able to see the components being loaded behind/under the loading indicator, then it would be more challenging and would probably need more work than this proposed solution. But if you just want a loading indicator to show while the .map() prototype function is working, I believe this would do the trick:

constructor(props) {
    super(props);
    this.state = { loadingIndicator : null };
}

getArrayOfMyComponents() {
    return myArray.map((arr, index) => {
        if (index === 0) {
            const loadingIndicator = <Loading/>;
            this.setState({ loadingIndicator : loadingIndicator });
        } else if (index === myArray.length - 1) {
            this.setState({ loadingIndicator : null });
        }
        return ( <MyComponent title={arr.title} /> );
    });
}

render() {
    const arrayOfMyComponents = this.getArrayOfMyComponents();
    return (
        <div>
            {this.state.loadingIndicator}
            {arrayOfMyComponents}
        </div>
    );
}

Array.prototype.map() is really just a fancier version of Array.prototype.forEach(). So we can leverage that fact to launch the display of the loading indicator on the first iteration and remove it on the last.

Upvotes: 0

Related Questions