Reputation: 409
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
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
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
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