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 };
CodePudding user response:
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!)
CodePudding user response:
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,
};