0
\$\begingroup\$

I have a custom component with a List. I need to know if this way is the best for show a Spinner while the fetch is working.

I'm using child props for that, but I don't know if this way is the correct.

import React, { Component, PropTypes } from 'react';
import demoData from './demodata';
// Other import stuff...
export default class HomeScreen extends Component {
 // Constructor component
 constructor(props) {
 super(props);
 const ds = new ListView.DataSource({
 rowHasChanged: (r1, r2) => r1 !== r2,
 sectionHeaderHasChanged: (s1, s2) => s1 !== s2
 });
 this.state = {
 dataSource: ds.cloneWithRows(demoData),
 loading: true
 };
 // Service for fetching data
 this.service = new ServiceApp();
 }
 componentDidMount() {
 this
 .fetchData();
 }
 // Simulate fetchData
 fetchData() { 
 const self = this;
 setTimeout(() => {
 self.setState({
 loading: false
 });
 }, 4000); 
 }
 render() {
 const component = this.state.loading ? <Spinner /> : (<ListView
 style={styles.container}
 dataSource={this.state.dataSource}
 renderRow={data => <Row {...data} />} />);
 return ( 
 <Content>
 {component}
 </Content> 
 );
 }
}
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Mar 8, 2017 at 16:08
\$\endgroup\$
2
  • \$\begingroup\$ "I'm using child props for that, but I don't know if this way is the correct." Does it work as intended? \$\endgroup\$ Commented Mar 8, 2017 at 16:19
  • \$\begingroup\$ Yes, works perfect, but I would like to know about performance re-render ;) \$\endgroup\$ Commented Mar 8, 2017 at 16:20

1 Answer 1

1
\$\begingroup\$

The way I do it is to have both the Spinner and the components in the render and pass it the loading prop and inside the Spinner component it will render the spinner if loading is set to true and return null if its set to false. That way you're not re-rendering the whole listview when you toggle it on and off.

this.state = {
 loading: false,
} //in the contructor
componentDidMount() {
this.setState({ loading: true }, () => this.fetchData());
}
// Simulate fetchData
fetchData = () => { 
 //const self = this; you don't need this line
 setTimeout(() => {
 this.setState({
 loading: false
 });
 }, 4000); //after you receive the response, you set it back to false
}
render() {
 return ( 
 <Content>
 <Spinner visible={this.state.loading} />
 <ListView
 style={styles.container}
 dataSource={this.state.dataSource}
 renderRow={data => <Row {...data} />} />
 </Content> 
 );
}
answered Mar 8, 2017 at 16:24
\$\endgroup\$
8
  • \$\begingroup\$ Thank you so much, I like it more than my method... can you please tell me what is that? this.setState({ loading: true }, () => this.fetchData()); The second part of the object... \$\endgroup\$ Commented Mar 8, 2017 at 16:27
  • \$\begingroup\$ And... I need the self, if not, I have an error about setState \$\endgroup\$ Commented Mar 8, 2017 at 16:28
  • 1
    \$\begingroup\$ setState has an optional 2nd argument that gets invoked after state has been updated. So it's setting loading to true, then once done it will run this.fetchData. Also sorry you're right, but if you change fetchData(){ ... } to fetchData = () => { ... } it will work without having to do self=this. \$\endgroup\$ Commented Mar 8, 2017 at 16:31
  • \$\begingroup\$ Hi again :) One important thing, visible is not a valid prop of Spinner, do i need to create a "container component" for adding that? Thanks \$\endgroup\$ Commented Mar 8, 2017 at 16:50
  • 1
    \$\begingroup\$ So you have two options: you can create a container around that like you said and return the spinner or null depending on whether visible is true/false. option 2: Spinner is basically just the ActivityIndicator thats provided by RN so you can just use that instead and pass animating as the prop instead of visible. \$\endgroup\$ Commented Mar 8, 2017 at 16:55

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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