-
Notifications
You must be signed in to change notification settings - Fork 1.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor post threads to use react query #1851
Conversation
import {RQKEY as POST_RQKEY, getCachedPost} from './post' | ||
import {ThreadViewPreference} from '../models/ui/preferences' | ||
|
||
export const RQKEY = (uri: string) => ['post-thread', uri] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not positive we'd really see an issue with this, but we might want to include the user did or something in this keyset so that switching users without a reload to clear memory never results in stale data being shown from cache.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assumed we'd drop all RQ cache on a session change
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be nice to have our React Query Keys strongly typed in one place so we can refer to them for future updates. A very simple factory model should work: https://tkdodo.eu/blog/effective-react-query-keys#use-query-key-factories
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm +1 to this, nice to have a quick reference to what query keys are out there
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually @ansh does it change your mind any if we have separate query hooks for each query like Paul has here? I.e. usePostQuery
instead of useQuery(RQKEY('uri'), () => {})
. So finding all usages is pretty easy either way.
src/state/queries/post-thread.ts
Outdated
) | ||
} | ||
|
||
export function sortThreadSkeleton( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These functions are so clear 🥺 I love them
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh yeah why dont you marry them
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would love a comment overview of how this function sorts the posts for future contributors:
// 1. If node is not a post return it unmodified, otherwise continue.
// 2. If the node has replies, start the sorting process.
// 3. Retrieve the cached post for the current node using its URI.
// 4. Sort the replies array in place using a custom comparator.
// 5. Inside the comparator, give priority to posts over non-posts.
// 6. Retrieve cached posts for both comparison nodes using their URIs.
// 7. If the cached post for 'a' is not found, it is moved down in the sort order.
// 8. If the cached post for 'b' is not found, it is moved up in the sort order.
// 9. Check if the author of post 'a' is the original poster (OP) and the same for post 'b'.
// 10. If both are by the OP, sort by the timestamp 'indexedAt' to get the oldest post.
// 11. If only 'a' is by the OP, it gets higher priority.
// 12. If only 'b' is by the OP, 'a' gets higher priority.
// 13. If user preference is to prioritize followed users, compare the following status of each post's author.
// 14. Sort by followed status, giving priority to followed user's posts.
// 15. If sorting by 'oldest', sort by 'indexedAt' to get the oldest post.
// 16. If sorting by 'newest', sort by 'indexedAt' in reverse to get the newest post.
// 17. If sorting by 'most-likes', compare like counts; in case of a tie, use 'indexedAt' to prioritize newer posts.
// 18. If sorting by 'random', return a random order by using Math.random.
// 19. Default to sorting by 'indexedAt' in reverse if no other conditions are met.
// 20. Recursively apply the sorting function to each reply.
// 21. Finally, return the sorted node.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not a huge fan of describing code a second time in the comments -- only summarizing or explaining
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: conceptually I think I like @gaearon's distinction between state and "cache" i.e. a local cache of remote data that only changes on a server. In respect to that, I'm kinda inclined to say we should put queries in a src/data/*
dir or something outside the state dir, but that's a very soft opinion. Remote cache/data is "state" in a way too. Idk!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
totally open to different directory structures here
} from '@tanstack/react-query' | ||
import {useSession} from '../session' | ||
|
||
export const RQKEY = (postUri: string) => ['post', postUri] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be nice to have this in a typed key generating factory as previously mentioned
return res.data.posts[0] | ||
} | ||
|
||
throw new Error('No data') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this error propagated somewhere?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it becomes RQ error state, right?
}) | ||
return {likeCount} | ||
}, | ||
onSuccess(data, variables) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
React Query v5 is out which simplifies the optimistic update workflow. We no longer have to manually update the cache every time:
https://medium.com/@stojanovic.nemanja71/optimistic-updates-in-tanstack-query-v5-dfbcbb124113
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This applies to other optimistic updates as well. Not adding the comment everywhere fyi.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The link above is how we should do things in most cases. In this case, the post shadow is synced across components and it's better to put in these handlers
isRefetching, | ||
data: threadSkeleton, | ||
} = usePostThreadQuery(resolvedUri) | ||
const {data: rootPost} = usePostQuery(threadSkeleton?.uri) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Love how the code is simplified!
Post hidden | ||
</Text> | ||
<Text type="md" style={[pal.text, s.mb10]}> | ||
You have blocked the author or you have been blocked by the author. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please merge with main and add <Trans>
here
<CenteredView> | ||
<View style={[pal.view, pal.border, styles.notFoundContainer]}> | ||
<Text type="title-lg" style={[pal.text, s.mb5]}> | ||
Post hidden |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
<Trans>
here too
This PR refactors the Post Thread code to use React Query (RQ).
In addition to refactoring the Post Thread, this PR introduces a "Post Shadow" cache which is used for optimistic updates that we want to keep synced across views (like, repost, and deletion state).
Some notes:
This PR is using a temporaryuseSession
hook that lightly wraps the existing session manager.2
to the filename, since there's still existing code depending on them.