Issue
I'm building a social media app in react native. I'm using react-redux with redux-toolkit and flashlist, along with other libraries.
My redux state (simplified) looks like this: (postState is the name of the reducer)
{
feeds: {},
posts: [],
accounts: []
}
When I fetch the home feed, all the posts are fetched. To prevent duplicate data (a user can have multiple posts on the home feed), I split the data into posts and accounts. Every post is stored with only the account ID (and not the full account data). I store an array of ids in the feed object. The key of each array is the id of the specific feed.
{
feed: {
home: [1,2,3,4],
user_1: [2,4],
...
}
}
When fetching the posts for the feed, I have the following code:
const getFeedid = (state, feedId) => feedId;
const getFeeds = state => state.feeds;
const getPosts = state => state.posts;
const getAccounts = state => state.accounts;
const getPostsForFeed = createSelector([getFeeds, getPosts, getAccounts], (feedId, feeds, posts, accounts) => {
const ids = feeds[feedId];
let postsArr = posts.filter(e => ids.includes(e.postId));
let arr = [];
postsArr.forEach((post) => {
const account = accounts.find(e => e.accountId === post.accountId);
return {
...post,
account
};
});
return postsArr;
});
const posts = useSelector(state => getPostsForFeed(state.postsState, 'home'), shallowEqual);
In a flashlist, I display these items.
// probably not neccessary?
const memoizedPosts = useMemo(() => posts, [posts]);
const renderItems = useCallback(({item}) => {
return (<Post item={item} />);
}, []);
const keyExtractor = useCallback(item => item.postId.toString(), []);
const [viewableIndexes, setViewableIndexes] = useState([]);
const onViewableItemsChanged = useCallback(({viewableItems}) => {
setViewableIndexes(viewableItems.map(e => e.index));
}, []);
<FlashList
keyExtractor={keyExtractor}
renderItems={renderItems}
items={memoizedPosts}
onViewableItemsChanged={onViewableItemsChanged}
/>
What is the problem?
When I scroll up or down, the viewableIndexes state changes. This is normal. But the posts in the redux state keep refreshing.
useEffect(() => {
console.log('posts in redux changed');
}, [posts]);
When I add this useEffect to my code, whenever I scroll up or down in the flashlist, the useEffect-code is triggered multiple times. I don't get it, because the content of the redux state is not changed, only the viewableIndex-state is changed.
The <Post />
-component is in a React.memo().
My question is:
why does this useEffect code runs whenever I scroll, because this means that "posts" has changed whenever I scroll. I'm starting to learn createSelector (I never used it before but I found out this would be a good use case). Maybe there is something wrong in my createSelector? I'm not changing the redux-state in other components while scrolling. I'm literally only scrolling, I'm not changing redux state (but I am changing a state in the component with the flashlist itself).
When I remove this useState-change, it works.
Solution
The issue may arise because this line is placed inside the component:
const getPostsForFeed = createSelector(...
which results getPostsForFeed
being recreated every time the content renders, so the memorized state of input-selector
is lost. Have a look at https://react-redux.js.org/api/hooks#using-memoizing-selectors .
Answered By - Cam Hoang
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.