From 20d18f3588978d32c833d5f82e344a46da19fcf2 Mon Sep 17 00:00:00 2001 From: Austin Chen Date: Tue, 1 Mar 2022 16:32:31 -0800 Subject: [PATCH] Client-side render pages that need auth These pages are now client-side rendered: - /home - /leaderboards - /market/... - /fold/... --- web/hooks/use-contract.ts | 2 +- web/hooks/use-propz.ts | 30 +++++++++++++++++++++++++ web/pages/[username]/[contractSlug].tsx | 15 +++++++++++-- web/pages/fold/[...slugs]/index.tsx | 20 ++++++++++++++--- web/pages/home.tsx | 8 ++++++- web/pages/leaderboards.tsx | 7 +++++- 6 files changed, 74 insertions(+), 8 deletions(-) create mode 100644 web/hooks/use-propz.ts diff --git a/web/hooks/use-contract.ts b/web/hooks/use-contract.ts index d48cd26a..ceaa125b 100644 --- a/web/hooks/use-contract.ts +++ b/web/hooks/use-contract.ts @@ -29,7 +29,7 @@ export const useContractWithPreload = ( useEffect(() => { if (contractId) return listenForContract(contractId, setContract) - if (contractId !== null) + if (contractId !== null && slug) getContractFromSlug(slug).then((c) => setContractId(c?.id || null)) }, [contractId, slug]) diff --git a/web/hooks/use-propz.ts b/web/hooks/use-propz.ts new file mode 100644 index 00000000..3687c725 --- /dev/null +++ b/web/hooks/use-propz.ts @@ -0,0 +1,30 @@ +import _ from 'lodash' +import { useRouter } from 'next/router' +import { useState, useEffect } from 'react' + +type PropzProps = { + params: any +} + +// getStaticPropz should exactly match getStaticProps +// This allows us to client-side render the page for authenticated users. +// TODO: Could cache the result using stale-while-revalidate: https://swr.vercel.app/ +export function usePropz( + getStaticPropz: (props?: PropzProps) => Promise, + // Dynamic routes will need the query params from the router + needParams?: boolean +) { + // Get params from router + const router = useRouter() + const params = router.query + + const [propz, setPropz] = useState(undefined) + useEffect(() => { + if (needParams && _.isEmpty(params)) { + return + } + // @ts-ignore + getStaticPropz({ params }).then((result) => setPropz(result.props)) + }, [params]) + return propz +} diff --git a/web/pages/[username]/[contractSlug].tsx b/web/pages/[username]/[contractSlug].tsx index 72cacd3f..f90da12e 100644 --- a/web/pages/[username]/[contractSlug].tsx +++ b/web/pages/[username]/[contractSlug].tsx @@ -29,8 +29,9 @@ import { useFoldsWithTags } from '../../hooks/use-fold' import { listAllAnswers } from '../../lib/firebase/answers' import { Answer } from '../../../common/answer' import { AnswersPanel } from '../../components/answers/answers-panel' +import { usePropz } from '../../hooks/use-propz' -export async function getStaticProps(props: { +export async function getStaticPropz(props: { params: { username: string; contractSlug: string } }) { const { username, contractSlug } = props.params @@ -64,7 +65,7 @@ export async function getStaticProps(props: { } } -export async function getStaticPaths() { +export async function getStaticPathz() { return { paths: [], fallback: 'blocking' } } @@ -77,6 +78,16 @@ export default function ContractPage(props: { slug: string folds: Fold[] }) { + // @ts-ignore + props = usePropz(getStaticPropz, true) ?? { + contract: null, + username: '', + comments: [], + answers: [], + bets: [], + slug: '', + folds: [], + } const user = useUser() const contract = useContractWithPreload(props.slug, props.contract) diff --git a/web/pages/fold/[...slugs]/index.tsx b/web/pages/fold/[...slugs]/index.tsx index 39c0845b..9040a3b7 100644 --- a/web/pages/fold/[...slugs]/index.tsx +++ b/web/pages/fold/[...slugs]/index.tsx @@ -40,8 +40,9 @@ import FeedCreate from '../../../components/feed-create' import { SEO } from '../../../components/SEO' import { useTaggedContracts } from '../../../hooks/use-contracts' import { Linkify } from '../../../components/linkify' +import { usePropz } from '../../../hooks/use-propz' -export async function getStaticProps(props: { params: { slugs: string[] } }) { +export async function getStaticPropz(props: { params: { slugs: string[] } }) { const { slugs } = props.params const fold = await getFoldBySlug(slugs[0]) @@ -124,7 +125,7 @@ async function toTopUsers(userScores: { [userId: string]: number }) { return topUsers.filter((user) => user) } -export async function getStaticPaths() { +export async function getStaticPathz() { return { paths: [], fallback: 'blocking' } } const foldSubpages = [undefined, 'activity', 'markets', 'leaderboards'] as const @@ -141,6 +142,19 @@ export default function FoldPage(props: { creatorScores: { [userId: string]: number } topCreators: User[] }) { + // @ts-ignore + props = usePropz(getStaticPropz, true) ?? { + fold: null, + curator: null, + contracts: [], + activeContracts: [], + activeContractBets: [], + activeContractComments: [], + traderScores: {}, + topTraders: [], + creatorScores: {}, + topCreators: [], + } const { curator, activeContractBets, @@ -154,7 +168,7 @@ export default function FoldPage(props: { const router = useRouter() const { slugs } = router.query as { slugs: string[] } - const page = (slugs[1] ?? 'activity') as typeof foldSubpages[number] + const page = (slugs?.[1] ?? 'activity') as typeof foldSubpages[number] const fold = useFold(props.fold?.id) ?? props.fold diff --git a/web/pages/home.tsx b/web/pages/home.tsx index 7bd305df..64543e67 100644 --- a/web/pages/home.tsx +++ b/web/pages/home.tsx @@ -20,8 +20,9 @@ import { useFindActiveContracts, } from '../hooks/use-active-contracts' import { useGetRecentBets } from '../hooks/use-bets' +import { usePropz } from '../hooks/use-propz' -export async function getStaticProps() { +export async function getStaticPropz() { const contractInfo = await getAllContractInfo() return { @@ -36,6 +37,11 @@ const Home = (props: { recentBets: Bet[] recentComments: Comment[] }) => { + props = usePropz(getStaticPropz) ?? { + contracts: [], + folds: [], + recentComments: [], + } const { contracts, folds, recentComments } = props const user = useUser() diff --git a/web/pages/leaderboards.tsx b/web/pages/leaderboards.tsx index fd2b8114..3e7caed2 100644 --- a/web/pages/leaderboards.tsx +++ b/web/pages/leaderboards.tsx @@ -5,8 +5,9 @@ import { Leaderboard } from '../components/leaderboard' import { Page } from '../components/page' import { getTopCreators, getTopTraders, User } from '../lib/firebase/users' import { formatMoney } from '../../common/util/format' +import { usePropz } from '../hooks/use-propz' -export async function getStaticProps() { +export async function getStaticPropz() { const [topTraders, topCreators] = await Promise.all([ getTopTraders().catch((_) => {}), getTopCreators().catch((_) => {}), @@ -26,6 +27,10 @@ export default function Leaderboards(props: { topTraders: User[] topCreators: User[] }) { + props = usePropz(getStaticPropz) ?? { + topTraders: [], + topCreators: [], + } const { topTraders, topCreators } = props return (