Make prefetching correctly use context cache (#835)

This commit is contained in:
Marshall Polaris 2022-09-01 19:38:09 -07:00 committed by GitHub
parent dca7205a47
commit 4406e53121
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 68 additions and 71 deletions

View File

@ -2,9 +2,9 @@ import clsx from 'clsx'
import { PencilIcon } from '@heroicons/react/outline' import { PencilIcon } from '@heroicons/react/outline'
import { User } from 'common/user' import { User } from 'common/user'
import { useEffect, useState } from 'react' import { useState } from 'react'
import { useFollowers, useFollows } from 'web/hooks/use-follows' import { useFollowers, useFollows } from 'web/hooks/use-follows'
import { prefetchUsers, useUser } from 'web/hooks/use-user' import { usePrefetchUsers, useUser } from 'web/hooks/use-user'
import { FollowList } from './follow-list' import { FollowList } from './follow-list'
import { Col } from './layout/col' import { Col } from './layout/col'
import { Modal } from './layout/modal' import { Modal } from './layout/modal'
@ -105,16 +105,9 @@ function FollowsDialog(props: {
const { user, followingIds, followerIds, defaultTab, isOpen, setIsOpen } = const { user, followingIds, followerIds, defaultTab, isOpen, setIsOpen } =
props props
useEffect(() => {
prefetchUsers([...followingIds, ...followerIds])
}, [followingIds, followerIds])
const currentUser = useUser() const currentUser = useUser()
const discoverUserIds = useDiscoverUsers(user?.id) const discoverUserIds = useDiscoverUsers(user?.id)
useEffect(() => { usePrefetchUsers([...followingIds, ...followerIds, ...discoverUserIds])
prefetchUsers(discoverUserIds)
}, [discoverUserIds])
return ( return (
<Modal open={isOpen} setOpen={setIsOpen}> <Modal open={isOpen} setOpen={setIsOpen}>

View File

@ -1,7 +1,7 @@
import clsx from 'clsx' import clsx from 'clsx'
import { User } from 'common/user' import { User } from 'common/user'
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import { prefetchUsers, useUserById } from 'web/hooks/use-user' import { usePrefetchUsers, useUserById } from 'web/hooks/use-user'
import { Col } from './layout/col' import { Col } from './layout/col'
import { Modal } from './layout/modal' import { Modal } from './layout/modal'
import { Tabs } from './layout/tabs' import { Tabs } from './layout/tabs'
@ -56,9 +56,7 @@ function ReferralsDialog(props: {
} }
}, [isOpen, referredByUser, user.referredByUserId]) }, [isOpen, referredByUser, user.referredByUserId])
useEffect(() => { usePrefetchUsers(referralIds)
prefetchUsers(referralIds)
}, [referralIds])
return ( return (
<Modal open={isOpen} setOpen={setIsOpen}> <Modal open={isOpen} setOpen={setIsOpen}>

View File

@ -9,9 +9,10 @@ import {
listenForHotContracts, listenForHotContracts,
listenForInactiveContracts, listenForInactiveContracts,
listenForNewContracts, listenForNewContracts,
getUserBetContracts,
getUserBetContractsQuery, getUserBetContractsQuery,
} from 'web/lib/firebase/contracts' } from 'web/lib/firebase/contracts'
import { QueryClient } from 'react-query' import { useQueryClient } from 'react-query'
export const useContracts = () => { export const useContracts = () => {
const [contracts, setContracts] = useState<Contract[] | undefined>() const [contracts, setContracts] = useState<Contract[] | undefined>()
@ -93,12 +94,12 @@ export const useUpdatedContracts = (contracts: Contract[] | undefined) => {
: undefined : undefined
} }
const queryClient = new QueryClient() export const usePrefetchUserBetContracts = (userId: string) => {
const queryClient = useQueryClient()
export const prefetchUserBetContracts = (userId: string) => return queryClient.prefetchQuery(['contracts', 'bets', userId], () =>
queryClient.prefetchQuery(['contracts', 'bets', userId], () => getUserBetContracts(userId)
getUserBetContractsQuery(userId)
) )
}
export const useUserBetContracts = (userId: string) => { export const useUserBetContracts = (userId: string) => {
const result = useFirestoreQueryData( const result = useFirestoreQueryData(

View File

@ -1,19 +1,22 @@
import { QueryClient } from 'react-query' import { useQueryClient } from 'react-query'
import { useFirestoreQueryData } from '@react-query-firebase/firestore' import { useFirestoreQueryData } from '@react-query-firebase/firestore'
import { DAY_MS, HOUR_MS } from 'common/util/time' import { DAY_MS, HOUR_MS } from 'common/util/time'
import { getPortfolioHistoryQuery, Period } from 'web/lib/firebase/users' import {
getPortfolioHistory,
const queryClient = new QueryClient() getPortfolioHistoryQuery,
Period,
} from 'web/lib/firebase/users'
const getCutoff = (period: Period) => { const getCutoff = (period: Period) => {
const nowRounded = Math.round(Date.now() / HOUR_MS) * HOUR_MS const nowRounded = Math.round(Date.now() / HOUR_MS) * HOUR_MS
return periodToCutoff(nowRounded, period).valueOf() return periodToCutoff(nowRounded, period).valueOf()
} }
export const prefetchPortfolioHistory = (userId: string, period: Period) => { export const usePrefetchPortfolioHistory = (userId: string, period: Period) => {
const queryClient = useQueryClient()
const cutoff = getCutoff(period) const cutoff = getCutoff(period)
return queryClient.prefetchQuery(['portfolio-history', userId, cutoff], () => return queryClient.prefetchQuery(['portfolio-history', userId, cutoff], () =>
getPortfolioHistoryQuery(userId, cutoff) getPortfolioHistory(userId, cutoff)
) )
} }

View File

@ -1,11 +1,12 @@
import { prefetchUserBetContracts } from './use-contracts' import { usePrefetchUserBetContracts } from './use-contracts'
import { prefetchPortfolioHistory } from './use-portfolio-history' import { usePrefetchPortfolioHistory } from './use-portfolio-history'
import { prefetchUserBets } from './use-user-bets' import { usePrefetchUserBets } from './use-user-bets'
export function usePrefetch(userId: string | undefined) { export function usePrefetch(userId: string | undefined) {
const maybeUserId = userId ?? '' const maybeUserId = userId ?? ''
return Promise.all([
prefetchUserBets(maybeUserId) usePrefetchUserBets(maybeUserId),
prefetchUserBetContracts(maybeUserId) usePrefetchUserBetContracts(maybeUserId),
prefetchPortfolioHistory(maybeUserId, 'weekly') usePrefetchPortfolioHistory(maybeUserId, 'weekly'),
])
} }

View File

@ -1,16 +1,17 @@
import { QueryClient } from 'react-query' import { useQueryClient } from 'react-query'
import { useFirestoreQueryData } from '@react-query-firebase/firestore' import { useFirestoreQueryData } from '@react-query-firebase/firestore'
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import { import {
Bet, Bet,
getUserBets,
getUserBetsQuery, getUserBetsQuery,
listenForUserContractBets, listenForUserContractBets,
} from 'web/lib/firebase/bets' } from 'web/lib/firebase/bets'
const queryClient = new QueryClient() export const usePrefetchUserBets = (userId: string) => {
const queryClient = useQueryClient()
export const prefetchUserBets = (userId: string) => return queryClient.prefetchQuery(['bets', userId], () => getUserBets(userId))
queryClient.prefetchQuery(['bets', userId], () => getUserBetsQuery(userId)) }
export const useUserBets = (userId: string) => { export const useUserBets = (userId: string) => {
const result = useFirestoreQueryData( const result = useFirestoreQueryData(

View File

@ -1,6 +1,6 @@
import { useContext } from 'react' import { useContext } from 'react'
import { useFirestoreDocumentData } from '@react-query-firebase/firestore' import { useFirestoreDocumentData } from '@react-query-firebase/firestore'
import { QueryClient } from 'react-query' import { useQueryClient } from 'react-query'
import { doc, DocumentData } from 'firebase/firestore' import { doc, DocumentData } from 'firebase/firestore'
import { getUser, User, users } from 'web/lib/firebase/users' import { getUser, User, users } from 'web/lib/firebase/users'
@ -28,12 +28,13 @@ export const useUserById = (userId = '_') => {
return result.isLoading ? undefined : result.data return result.isLoading ? undefined : result.data
} }
const queryClient = new QueryClient() export const usePrefetchUser = (userId: string) => {
return usePrefetchUsers([userId])[0]
}
export const prefetchUser = (userId: string) => { export const usePrefetchUsers = (userIds: string[]) => {
const queryClient = useQueryClient()
return userIds.map((userId) =>
queryClient.prefetchQuery(['users', userId], () => getUser(userId)) queryClient.prefetchQuery(['users', userId], () => getUser(userId))
} )
export const prefetchUsers = (userIds: string[]) => {
userIds.forEach(prefetchUser)
} }

View File

@ -70,20 +70,16 @@ export function listenForBets(
) )
} }
export async function getUserBets( export async function getUserBets(userId: string) {
userId: string, return getValues<Bet>(getUserBetsQuery(userId))
options: { includeRedemptions: boolean } }
) {
const { includeRedemptions } = options export function getUserBetsQuery(userId: string) {
return getValues<Bet>( return query(
query(collectionGroup(db, 'bets'), where('userId', '==', userId)) collectionGroup(db, 'bets'),
) where('userId', '==', userId),
.then((bets) => orderBy('createdTime', 'desc')
bets.filter( ) as Query<Bet>
(bet) => (includeRedemptions || !bet.isRedemption) && !bet.isAnte
)
)
.catch((reason) => reason)
} }
export async function getBets(options: { export async function getBets(options: {
@ -124,22 +120,16 @@ export async function getBets(options: {
} }
export async function getContractsOfUserBets(userId: string) { export async function getContractsOfUserBets(userId: string) {
const bets: Bet[] = await getUserBets(userId, { includeRedemptions: false }) const bets = await getUserBets(userId)
const contractIds = uniq(bets.map((bet) => bet.contractId)) const contractIds = uniq(
bets.filter((b) => !b.isAnte).map((bet) => bet.contractId)
)
const contracts = await Promise.all( const contracts = await Promise.all(
contractIds.map((contractId) => getContractFromId(contractId)) contractIds.map((contractId) => getContractFromId(contractId))
) )
return filterDefined(contracts) return filterDefined(contracts)
} }
export function getUserBetsQuery(userId: string) {
return query(
collectionGroup(db, 'bets'),
where('userId', '==', userId),
orderBy('createdTime', 'desc')
) as Query<Bet>
}
export function listenForUserContractBets( export function listenForUserContractBets(
userId: string, userId: string,
contractId: string, contractId: string,

View File

@ -157,6 +157,10 @@ export function listenForUserContracts(
return listenForValues<Contract>(q, setContracts) return listenForValues<Contract>(q, setContracts)
} }
export function getUserBetContracts(userId: string) {
return getValues<Contract>(getUserBetContractsQuery(userId))
}
export function getUserBetContractsQuery(userId: string) { export function getUserBetContractsQuery(userId: string) {
return query( return query(
contracts, contracts,

View File

@ -254,6 +254,10 @@ export async function unfollow(userId: string, unfollowedUserId: string) {
await deleteDoc(followDoc) await deleteDoc(followDoc)
} }
export function getPortfolioHistory(userId: string, since: number) {
return getValues<PortfolioMetrics>(getPortfolioHistoryQuery(userId, since))
}
export function getPortfolioHistoryQuery(userId: string, since: number) { export function getPortfolioHistoryQuery(userId: string, since: number) {
return query( return query(
collectionGroup(db, 'portfolioHistory'), collectionGroup(db, 'portfolioHistory'),

View File

@ -18,8 +18,9 @@ export default async function handler(
return return
} }
const bets = await getUserBets(user.id, { includeRedemptions: false }) const bets = await getUserBets(user.id)
const visibleBets = bets.filter((b) => !b.isRedemption && !b.isAnte)
res.setHeader('Cache-Control', 'max-age=0') res.setHeader('Cache-Control', 'max-age=0')
return res.status(200).json(bets) return res.status(200).json(visibleBets)
} }