0

My situation is i have two FlatList component (A and B).

A is my first screen. I use react-navigation to navigate A to B , B will show back arrow on headerLeft. When i click the arrow it will back to A . But the FlatList data is still show B even it is really in A...

My data is from fetch API by react-redux, i think the problem is come from react-redux. Because i test a simple test without react-redux. The problem is gone.

I want to use react-redux create my project. I try to use shouldComponentUpdate like

shouldComponentUpdate = (nextProps, nextState) => {
    if (nextProps.movieList === this.props.movieList) {
      return false;
    }
    return true;
  };

It is still can't fix my problem when goBack() to another component

I console.log it try to find what is going on with my props data. When i navigate to B from A. My console.log will show like this, i find A component will be rendered... enter image description here

Then i click the back arrow on headerLeft to A. The screen is A but the data is still B add my console.log is empty at the same time.

I can't figure it out. Any help would be appreciated. Thanks in advance.

Here is my A component file (B is similar with A):

import React, { Component } from 'react';
import { 
  View, FlatList, Dimensions, 
  TouchableOpacity, Image,
  ActivityIndicator, Alert, Platform
} from 'react-native';
import { Icon } from 'react-native-elements';
import { connect } from 'react-redux';
import { fetchMainMovieList } from '../actions';

const { width, height } = Dimensions.get('window');
const equalWidth = (width / 2);

class MainActivity extends Component {
  static navigationOptions = ({ navigation }) => ({
    title: 'MainActivity',
    headerLeft: 
      <TouchableOpacity style={{ marginLeft: 10 }} onPress={() => navigation.navigate('DrawerOpen')} >
        <Icon name='menu' />
      </TouchableOpacity>
  });

  componentWillMount() {
    this.props.fetchMainMovieList();
  }

  renderItem({ item }) {
    return (
      <View>
        <Image 
          source={{ uri: item.photoHref }} 
          style={{ height: 220, width: equalWidth }} 
          resizeMode="cover" 
        />
      </View>
    );
  }

  render() {
    const movieData = this.props.movieList.movie;
    console.log('A component this.props=>');
    console.log(this.props);
    if (movieData === []) {
      return (
        <View style={styles.loadingStyle}>
          <ActivityIndicator />
        </View>
      );
    }
    return (
      <View style={{ flex: 1 }}>
        <FlatList
          data={movieData}
          renderItem={this.renderItem} 
          numColumns={2}
          horizontal={false}
          keyExtractor={(item, index) => index} 
        />
      </View>
    );
  }
}

const styles = {
  loadingStyle: {
    flex: 1, 
    flexDirection: 'column', 
    justifyContent: 'center', 
    alignItems: 'center'
  }
};

const mapStateToProps = (state) => {
  const movieList = state.movieList;

  return { movieList };
};

export default connect(mapStateToProps, { fetchMainMovieList })(MainActivity);

Here is my B component file:

import React, { Component } from 'react';
import { 
  View, FlatList, Dimensions, 
  Image, ActivityIndicator, Text
} from 'react-native';
import { connect } from 'react-redux';
import { fetchThisWeek } from '../actions';

const { width, height } = Dimensions.get('window');
const equalWidth = (width / 2);

class ThisWeek extends Component {
  static navigationOptions = ({ navigation }) => ({
    title: 'ThisWeek',
  });

  componentWillMount() {
    this.props.fetchThisWeek();
  }

  renderItem({ item }) {
    return (
      <View>
        <Image 
          source={{ uri: item.photoHref }} 
          style={{ height: 500, width: '100%' }} 
          resizeMode="cover" 
        />
      </View>
    );
  }

  render() {
    const movieData = this.props.movieList.movie;
    console.log('B component this.props=>');
    console.log(this.props);
    if (movieData === []) {
      return (
        <View style={styles.loadingStyle}>
          <ActivityIndicator />
        </View>
      );
    }
    return (
      <View style={{ flex: 1 }}>
        <FlatList
          data={movieData}
          renderItem={this.renderItem} 
          numColumns={1}
          horizontal={false}
          keyExtractor={(item, index) => index} 
        />
      </View>
    );
  }
}

const styles = {
  loadingStyle: {
    flex: 1, 
    flexDirection: 'column', 
    justifyContent: 'center', 
    alignItems: 'center'
  }
};

const mapStateToProps = (state) => {
  const movieList = state.movieList;

  return { movieList };
};

export default connect(mapStateToProps, { fetchThisWeek })(ThisWeek);

Here is my MyListReducer.js:

import { 
  MOVIELIST_MAINACTIVITY,
  MOVIELIST_THISWEEK,
  MOVIELIST_THEATER
} from '../actions/types';

const INITIAL_STATE = {};

export default (state = INITIAL_STATE, action) => {
  switch (action.type) {   
    case MOVIELIST_MAINACTIVITY:
      return action.payload;

    case MOVIELIST_THISWEEK:
      return action.payload;

    case MOVIELIST_THEATER:
      console.log(action.payload);
      return action.payload;

    default:
      return state;
  }
};
4
  • Are you using the same class for component B? Commented May 2, 2018 at 13:55
  • No, component B is another class component. I have post my B component file on my question. Commented May 2, 2018 at 13:58
  • Are the functions this.props.fetchMainMovieList(); this.props.fetchThisWeek(); both updating same object in redux? Commented May 2, 2018 at 14:02
  • Yes, they are in different switch-case , i update my reducer file on my question. Commented May 2, 2018 at 14:22

1 Answer 1

1

In your reducer you have added the fetched data into the main object in store, instead, you should have to maintain two different variables to save data of those different components separately. Try by changing the reducer as,

    import { 
      MOVIELIST_MAINACTIVITY,
      MOVIELIST_THISWEEK,
      MOVIELIST_THEATER
    } from '../actions/types';

    const INITIAL_STATE = {
      weeklyMovies:[],
      allMovies:[]
    };

    export default (state = INITIAL_STATE, action) => {
      switch (action.type) {   
        case MOVIELIST_MAINACTIVITY:
          return {
            ...state,
            allMovies:action.payload
         };

        case MOVIELIST_THISWEEK:
        return {
          ...state,
          weeklyMovies:action.payload
        };          

        case MOVIELIST_THEATER:
          console.log(action.payload);
          return action.payload;

        default:
          return {...state};
      }
    };

And in your component A and B you should change your mapStateToProps to read data from corresponding objects in store.

For MainActivity component

const mapStateToProps = (state) => {
  const movieList = state.allMovies;
  return { movieList };
};

and for ThisWeek component

const mapStateToProps = (state) => {
  const movieList = state.weeklyMovies;
  return { movieList };
};
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks @Rohith, i try your code i find i can get different this.props by different component now. Can i ask you one more thing? In my switch-case MOVIELIST_THEATER. All my other theater list use the same class component and the reducer. How do i avoid the problem if i try your code ? Thanks in advance.
You need to add one more object say, 'theatreList' in the reducer, save the value to it just like weeklyMovies and allMovies and access the value from this object in ur component
Thanks for your reply, it helps me a lot, Thank you !

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.