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 { User } from 'common/user'
import { useEffect, useState } from 'react'
import { useState } from 'react'
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 { Col } from './layout/col'
import { Modal } from './layout/modal'
@ -105,16 +105,9 @@ function FollowsDialog(props: {
const { user, followingIds, followerIds, defaultTab, isOpen, setIsOpen } =
props
useEffect(() => {
prefetchUsers([...followingIds, ...followerIds])
}, [followingIds, followerIds])
const currentUser = useUser()
const discoverUserIds = useDiscoverUsers(user?.id)
useEffect(() => {
prefetchUsers(discoverUserIds)
}, [discoverUserIds])
usePrefetchUsers([...followingIds, ...followerIds, ...discoverUserIds])
return (
<Modal open={isOpen} setOpen={setIsOpen}>

View File

@ -1,7 +1,7 @@
import clsx from 'clsx'
import { User } from 'common/user'
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 { Modal } from './layout/modal'
import { Tabs } from './layout/tabs'
@ -56,9 +56,7 @@ function ReferralsDialog(props: {
}
}, [isOpen, referredByUser, user.referredByUserId])
useEffect(() => {
prefetchUsers(referralIds)
}, [referralIds])
usePrefetchUsers(referralIds)
return (
<Modal open={isOpen} setOpen={setIsOpen}>

View File

@ -9,9 +9,10 @@ import {
listenForHotContracts,
listenForInactiveContracts,
listenForNewContracts,
getUserBetContracts,
getUserBetContractsQuery,
} from 'web/lib/firebase/contracts'
import { QueryClient } from 'react-query'
import { useQueryClient } from 'react-query'
export const useContracts = () => {
const [contracts, setContracts] = useState<Contract[] | undefined>()
@ -93,12 +94,12 @@ export const useUpdatedContracts = (contracts: Contract[] | undefined) => {
: undefined
}
const queryClient = new QueryClient()
export const prefetchUserBetContracts = (userId: string) =>
queryClient.prefetchQuery(['contracts', 'bets', userId], () =>
getUserBetContractsQuery(userId)
export const usePrefetchUserBetContracts = (userId: string) => {
const queryClient = useQueryClient()
return queryClient.prefetchQuery(['contracts', 'bets', userId], () =>
getUserBetContracts(userId)
)
}
export const useUserBetContracts = (userId: string) => {
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 { DAY_MS, HOUR_MS } from 'common/util/time'
import { getPortfolioHistoryQuery, Period } from 'web/lib/firebase/users'
const queryClient = new QueryClient()
import {
getPortfolioHistory,
getPortfolioHistoryQuery,
Period,
} from 'web/lib/firebase/users'
const getCutoff = (period: Period) => {
const nowRounded = Math.round(Date.now() / HOUR_MS) * HOUR_MS
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)
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 { prefetchPortfolioHistory } from './use-portfolio-history'
import { prefetchUserBets } from './use-user-bets'
import { usePrefetchUserBetContracts } from './use-contracts'
import { usePrefetchPortfolioHistory } from './use-portfolio-history'
import { usePrefetchUserBets } from './use-user-bets'
export function usePrefetch(userId: string | undefined) {
const maybeUserId = userId ?? ''
prefetchUserBets(maybeUserId)
prefetchUserBetContracts(maybeUserId)
prefetchPortfolioHistory(maybeUserId, 'weekly')
return Promise.all([
usePrefetchUserBets(maybeUserId),
usePrefetchUserBetContracts(maybeUserId),
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 { useEffect, useState } from 'react'
import {
Bet,
getUserBets,
getUserBetsQuery,
listenForUserContractBets,
} from 'web/lib/firebase/bets'
const queryClient = new QueryClient()
export const prefetchUserBets = (userId: string) =>
queryClient.prefetchQuery(['bets', userId], () => getUserBetsQuery(userId))
export const usePrefetchUserBets = (userId: string) => {
const queryClient = useQueryClient()
return queryClient.prefetchQuery(['bets', userId], () => getUserBets(userId))
}
export const useUserBets = (userId: string) => {
const result = useFirestoreQueryData(

View File

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

View File

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

View File

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

View File

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

View File

@ -18,8 +18,9 @@ export default async function handler(
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')
return res.status(200).json(bets)
return res.status(200).json(visibleBets)
}