I'm newbie to Reactjs. The problem I'm encountered:
When Article page loads in the first time, all is fine and there are 10 articles shown. When I click on the browser back button, and then I go to the Article page for the second time, the article-list will be duplicated (so, it will be 20 articles). If I do so again, it will be 30 articles and so on ..
I want to know, why the result of API call appends for the Redux and not replace? In other word, how can I clean the Redux on page load every time? The expected result is seeing always 10 item (articles) on the page Article
when I open it.
Here is a simplified of the element (for navigating to the list of articles) in the main page:
import Pages from "Constants/Pages";
const Component = () => {
const history = useHistory();
const navigateWithToken = (page) => {
history.push(page);
}
};
return (
<div className="d-flex align-items-center flex-column py-1 ">
<div
className="main-footer-btn-article"
onClick={() => navigateWithToken(Pages.Articles)}
></div>
<span className="main-footer-btn-text">Articles</span>
</div>
)
};
export const ArticlesBtn = memo(Component);
Also, here is the Article
page:
import { memo, useEffect } from "react";
import { useHistory } from "react-router-dom";
import { useSelector, useDispatch } from "react-redux";
import PostItems from "SharedComponents/PostItems";
import { getAllPosts } from "Redux/Actions";
import Pages from "Constants/Pages";
const Page = () => {
const posts = useSelector((state) => state?.articles?.posts?.items);
const dispatch = useDispatch();
const { push } = useHistory();
useEffect(() => {
dispatch(getAllPosts());
}, []);
const onClickPost = (item) => {
push({
pathname: Pages.SingleArticle,
state: {
postId: item.id,
title: item.subject,
is_saved: item.is_saved,
},
});
};
return (
<div className="full-height overflow-auto">
{
posts?.map((item, index) => {
return (
<PostItems
{...item}
key={item.id}
index={index}
onClickPost={() => onClickPost(item)}
/>
);
})
}
</div>
);
};
export default memo(Page);
Also here is the API call:
const getAllPosts = (page = 1) => {
return async (dispatch: ReduxDispatch) => {
//"posts?for=for_website"
dispatch(toggleLoading(true));
try {
const { data } = await axios({
method: "GET",
url: "posts?for=for_mobile",
params: { page: page },
});
const items = data?.data?.data;
const pagination = {
current_page: data.data.current_page,
last_page: data.data.last_page,
};
dispatch(
dispatchItemToRedux({
type: ReducerTypes.GET_ALL_POSTS,
payload: {
items,
pagination,
},
})
);
} catch (err) {
return Promise.reject(err);
} finally {
dispatch(toggleLoading(false));
}
};
};
Also, here is the reducer:
import ReducerTypes from "Redux/Types/ReducerTypes";
const INITIAL_STATE = {
posts: {
items: [],
pagination: {}
},
singlePost: {
id: null,
subject: null,
caption: null,
deep_link: null,
short_link: null,
total_comments: null,
total_likes: null,
total_views: null,
created: null,
medias: null,
likes: []
},
postComments: []
};
function articleReducer(state = INITIAL_STATE, action) {
switch (action.type) {
case ReducerTypes.GET_ALL_POSTS:
return {
...state,
posts: {
items: state.posts.items.concat(action.payload.items),
pagination: action.payload.pagination
}
};
case ReducerTypes.GET_SINGLE_POST:
return {
...state,
singlePost: action.payload
};
case ReducerTypes.GET_POST_COMMENTS:
return {
...state,
postComments: action.payload
};
case ReducerTypes.GET_POST_LIKES:
return {
...state,
singlePost: {
...state.singlePost,
likes: action.payload
}
};
default:
return state;
};
};
export default articleReducer;
CodePudding user response:
case ReducerTypes.GET_ALL_POSTS:
return {
...state,
posts: {
items: action.payload.items,
pagination: action.payload.pagination
}
};
Try omitting that .concat()