skip to Main Content

I’m new in redux, I’m using react native hooks and redux. my problem is that after opening the articleScreen.js page then clicking the back button and opening the articleScreen.js page again, the data is rendered again so that there is the same data and display the same data repeatedly when clicked on the articleScreen.js page. is there something wrong with my code below?.

=> ArticleScreen.js

 const ArticleScreen = () => {
  const dispatch = useDispatch();
  const data = useSelector((state) => state.articleReducer.data);
  const isLoading = useSelector((state) => state.articleReducer.isLoading);
  const [loadingMore, setLoadingMore] = useState(false);
  const [page, setPage] = useState(1);
  const currentPage = useSelector((state) => state.articleReducer.currentPage);
  const totalPage = useSelector((state) => state.articleReducer.totalPage);
  const nextPage = useSelector((state) => state.articleReducer.nextPage);

  useEffect(() => {
    dispatch(fetchingArticle({ page: 1 }));
  }, [])

  const _renderItem = ({ item, index }) => {
    return (
      <TouchableOpacity
        key={`${item.id} ${page}`}
        style={{ marginBottom: 16 }}
      >
        <View style={{ flexDirection: 'row' }}>
          <View style={{ flex: 1 }}>
            <Text>{item.title}</Text>
          </View>
        </View>
      </TouchableOpacity>
    );
  };

  const handleLoadMoreData = () => {
    if (!isLoading) {
      setLoadingMore(true)
      if (nextPage <= totalPage) {
        dispatch(fetchingArticle(nextPage));
      } else {
        setLoadingMore(false)
      }
    }
  }

  return (
    <>
      <View>
        <FlatList
          data={data}
          renderItem={_renderItem}
          keyExtractor={item => `${item.id}`}
          onEndReached={handleLoadMoreData}
          onEndReachedThreshold={0.01}
          ListFooterComponent={
            loadingMore && (
              <View
                style={{
                  marginVertical: 30,
                }}>
                <ActivityIndicator
                  size="large"
                  color={Colors.onSurface}
                />
              </View>
            )
          }
        />
      </View>
    </>
  );
};

export default ArticleScreen;

=> store.js

const middleware = applyMiddleware(thunk);

// Root Reducer
const rootReducer = combineReducers({
  articleReducer: ArticleReducer,
});

// Redux Store
const store = createStore(
  rootReducer,
  middleware
)

export default store;

=> ArticleAction.js

export const fetchArticleRequest = () => ({
  type: 'FETCH_ARTICLE_REQUEST',
});

export const fetchArticleSuccess = (data) => ({
  type: 'FETCH_ARTICLE_SUCCESS',
  payload: data.data
});

export const fetchArticleFailure = (error) => ({
  type: 'FETCH_ARTICLE_FAILURE',
  payload: error
});

export const fetchingArticle = (page) => {
  return async dispatch => {
    dispatch(fetchArticleRequest());
    return apiRequest.get(URL.articles + '?page=' + page).then((response) => {
      dispatch(fetchArticleSuccess(response.data));
    })
      .catch((error) => {
        dispatch(fetchArticleFailure("Request Data Error"))
      })
  }
}

=> ArticleReducer.js

  const initialState = {
  data: [],
  error: '',
  isLoading: false,
  refreshing: false,
  currentPage: 1,
  totalPage: 1,
  nextPage: 0,
  totalData: 0
};

const ArticleReducer = (state = initialState, action) => {
  switch (action.type) {
    case 'FETCH_ARTICLE_REQUEST':
      return {
        ...state,
        isLoading: true,
        refreshing: true,
      };
    case 'FETCH_ARTICLE_SUCCESS':
      return {
        ...state,
        data: state.data.concat(action.payload.data),
        isLoading: false,
        refreshing: false,
        currentPage: action.payload.current_page,
        totalPage: action.payload.last_page,
        nextPage: action.payload.current_page + 1,

      };
    case 'FETCH_ARTICLE_FAILURE':
      return {
        ...state,
        error: action.error,
        isLoading: false,
        refreshing: false,
      };

    default:
      return state;
  }
};

export { ArticleReducer };

2

Answers


  1. I do not know Redux but maybe you need to load your data only one time and not every time you call your page unless you clear that you have before fetching them.

    I will let other people who know better that me redux (I can’t comment so do not count this answer as answer!)

    Login or Signup to reply.
  2. The problem is with you reducer. You are concating previous data with new data
    as

    data: state.data.concat(action.payload.data)
    

    In case ‘FETCH_ARTICLE_SUCCESS’: Change above line to

    data: action.payload.data
    

    Like

    case 'FETCH_ARTICLE_SUCCESS':
          return {
            ...state,
            data: action.payload.data,
            isLoading: false,
            refreshing: false,
            currentPage: action.payload.current_page,
            totalPage: action.payload.last_page,
            nextPage: action.payload.current_page + 1,
    
          };
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search