code.hesh
code.hesh

Reputation: 24

React Native FlatList is not rendering using state value

I'm getting data from API (using Redux Saga) and I want to show the data in a FlatList. In ComponentDidMount I'm dispatching the action to hit the API. Data are getting without any issue. But for the first time , data is not showing in the flatlist. If I enter Ctrl + S (Save) in VS code data is showing. I want to have set

class MovieDetailsScreen extends Component {
constructor(props) {
    super(props);
    this.state = {
        data:[],

    };
}

componentDidMount(){
   this.props.getMovieData();
   if(this.props.movieList){
       this.setState({data:movieList})
   }
}


renderItem = ({ item }) => {
    return(
    <View style={styles.mainContainer}> 

        <View style={styles.textContainer}>
            <Text >{item.movieName}</Text>
            <Text >{item.movieDescription}</Text>
        </View>


    )
}

render() {

    return (
        <View >

            <FlatList  
                keyExtractor={(item, index) => index.toString()}
                data={this.state.data}
                renderItem={this.renderItem}
            /> 

        </View>

    );
}

}

function mapStateToProps(state) {

return {
   movieList : state.movieListReducer.movieList

};

}

export function mapDispatchToProps(dispatch) { return{

     getMovieData: () => dispatch(movieListActions.getMovieData()),

}

}

export default connect( mapStateToProps, mapDispatchToProps )(MovieDetailsScreen);

I tried adding a loader in flatlist until the data is getting loaded , but it's not working. Please note that I need to use setState({data:movieList}) because in future I have more implementations , so I couldn't use this.props.movieList in flatlist data

Upvotes: 0

Views: 782

Answers (2)

theocikos
theocikos

Reputation: 2004

You should create a new function to hold the fetching of the data and to give you an option to create the loader.

First add a loading option to your state:

this.state = {
    data:[],
    loading: false,
};

Then create the function:

   fetchMovieList = () => {
       this.setState({ loading: true })
    this.props.getMovieData()
     .finally( () => {
         this.setState({ loading: false })
            if(this.props.movieList){
              this.setState({data:movieList})
      }
  }

Call the function in componentDidMount:

componentDidMount(){
   this.fetchMovieList();
}

and in your render() set according to loading if it true show an empty view and if it is false show the flat list:

render() {
    if (this.state.loading) {
        return (
            <View>
                <Text> Loading </Text>
            </View>
        );
    }
    return (
        <View >
        <FlatList  
            keyExtractor={(item, index) => index.toString()}
            data={this.state.data}
            renderItem={this.renderItem}
        /> 

    </View>

);
}
Instead of the text loading you can use the ActivityIndicator provided by react-native. Please check if i missed any semicolon or parentheses.

Upvotes: 1

Anurodh Singh
Anurodh Singh

Reputation: 812

You should call the this.setState({data:movieList}) method in componentDidUpdate because componentDidMount only runs for the first time.

Your code should be like this,

componentDidMount(){
   this.props.getMovieData();
}

// This method will execute everytime a state or props change.
componentDidUpdate(prevProps){
   if(this.props.movieList != prevProps.movieList){
       this.setState({data:this.props.movieList})
   }
}

Upvotes: 1

Related Questions