diff --git a/components/Profile/useProfile.ts b/components/Profile/useProfile.ts index 7c07b85e96..d4770a2c67 100644 --- a/components/Profile/useProfile.ts +++ b/components/Profile/useProfile.ts @@ -1,31 +1,13 @@ -import { useEffect, useState } from 'react' -import { Connection, PublicKey } from '@solana/web3.js' +import { PublicKey } from '@solana/web3.js' import { CivicProfile, Profile as BaseProfile } from '@civic/profile' import useWalletOnePointOh from '@hooks/useWalletOnePointOh' import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' +import { useQuery } from '@tanstack/react-query' type Profile = BaseProfile & { exists: boolean } -const profiles = new Map>() - -const getProfile = async ( - publicKey: PublicKey, - connection?: Connection -): Promise => { - const cached = profiles.get(publicKey.toBase58()); - if (cached) return cached; - - const options = connection ? { solana: { connection } } : undefined; - - const promise = CivicProfile.get(publicKey.toBase58(), options); - - profiles.set(publicKey.toBase58(), promise) - - return promise; -} - const profileIsSet = (profile: BaseProfile): boolean => !!profile.name || !!profile.image || !!profile.headline @@ -34,25 +16,24 @@ export const useProfile = ( ): { profile: Profile | undefined; loading: boolean } => { const connection = useLegacyConnectionContext() const connectedWallet = useWalletOnePointOh() - const [profile, setProfile] = useState() - const [loading, setLoading] = useState(true) const profileWalletPublicKey = publicKey || connectedWallet?.publicKey - - useEffect(() => { - if (profileWalletPublicKey) { - getProfile(profileWalletPublicKey, connection?.current).then( - (profile) => { - setProfile({ - ...profile, - exists: profileIsSet(profile), - }) - setLoading(false) - } - ) + const options = connection + ? { solana: { connection: connection?.current } } + : undefined + + const { data: profile, isLoading } = useQuery( + ['profile', profileWalletPublicKey], + // @ts-ignore we won't run this if there is no profileWalletPublicKey + () => CivicProfile.get(profileWalletPublicKey?.toBase58(), options), + { + enabled: !!profileWalletPublicKey, // Only run query if profileWalletPublicKey is available + select: (data) => ({ + ...data, + exists: profileIsSet(data), + }), } - // eslint-disable-next-line react-hooks/exhaustive-deps -- TODO please fix, it can cause difficult bugs. You might wanna check out https://bobbyhadz.com/blog/react-hooks-exhaustive-deps for info. -@asktree - }, [publicKey, connectedWallet?.publicKey, connection.current]) + ) - return { profile, loading } + return { profile, loading: isLoading } } diff --git a/components/chat/DiscussionPanel.tsx b/components/chat/DiscussionPanel.tsx index f5723cc846..aaf49322a0 100644 --- a/components/chat/DiscussionPanel.tsx +++ b/components/chat/DiscussionPanel.tsx @@ -1,6 +1,5 @@ import { useMemo } from 'react' import DiscussionForm from './DiscussionForm' -import Comment from './Comment' import { useQuery } from '@tanstack/react-query' import { GOVERNANCE_CHAT_PROGRAM_ID, @@ -8,6 +7,7 @@ import { } from '@solana/spl-governance' import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' import { useSelectedProposalPk } from '@hooks/queries/proposal' +import LazyLoadComment from './LazyLoadComment' export const useChatMessagesQuery = () => { const connection = useLegacyConnectionContext() @@ -57,7 +57,7 @@ const DiscussionPanel = () => { {sortedMessages?.map((cm) => ( - + ))} ) diff --git a/components/chat/LazyLoadComment.tsx b/components/chat/LazyLoadComment.tsx new file mode 100644 index 0000000000..773c441727 --- /dev/null +++ b/components/chat/LazyLoadComment.tsx @@ -0,0 +1,19 @@ +import React from 'react' +import { useInView } from 'react-intersection-observer' +import Comment from './Comment' +import { ChatMessage } from '@solana/spl-governance' + +const LazyLoadComment = ({ chatMessage }: { chatMessage: ChatMessage }) => { + const { ref, inView } = useInView({ + /* Optional options */ + triggerOnce: true, + }) + + return ( +
+
{inView && }
+
+ ) +} + +export default LazyLoadComment diff --git a/package.json b/package.json index e5ee3d6b38..f7ef14f169 100644 --- a/package.json +++ b/package.json @@ -158,11 +158,12 @@ "react-headless-pagination": "0.1.0", "react-hook-form": "7.31.3", "react-icons": "4.11.0", + "react-intersection-observer": "9.5.3", "react-markdown": "7.0.0", "react-portal": "4.2.2", "react-responsive": "9.0.0-beta.10", "react-virtualized-auto-sizer": "1.0.6", - "react-window": "1.8.9", + "react-window": "1.8.10", "remark-gfm": "3.0.1", "superstruct": "0.15.4", "swr": "1.3.0", diff --git a/pages/_error.js b/pages/_error.js index 1068f15f10..1254ef1be4 100644 --- a/pages/_error.js +++ b/pages/_error.js @@ -23,8 +23,8 @@ MyError.getInitialProps = async (context) => { // getInitialProps has run errorInitialProps.hasGetInitialPropsRun = true - // Returning early because we don't want to log 404 errors to Sentry. - if (res?.statusCode === 404) { + // Returning early because we don't want to log 404 or 403 errors to Sentry. + if (res?.statusCode === 404 || res?.statusCode === 403) { return errorInitialProps } diff --git a/pages/dao/[symbol]/proposal/[pk]/index.tsx b/pages/dao/[symbol]/proposal/[pk]/index.tsx index 40f03beca6..df6d65f4b1 100644 --- a/pages/dao/[symbol]/proposal/[pk]/index.tsx +++ b/pages/dao/[symbol]/proposal/[pk]/index.tsx @@ -85,7 +85,7 @@ const Proposal = () => { proposal.account.state === ProposalState.ExecutingWithErrors) return ( -
+
{proposal ? ( <> diff --git a/yarn.lock b/yarn.lock index eac54481d0..bc1e8391c0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13656,6 +13656,11 @@ react-icons@^4.3.1: resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-4.7.1.tgz#0f4b25a5694e6972677cb189d2a72eabea7a8345" integrity sha512-yHd3oKGMgm7zxo3EA7H2n7vxSoiGmHk5t6Ou4bXsfcgWyhfDKMpyKfhHR6Bjnn63c+YXBLBPUql9H4wPJM6sXw== +react-intersection-observer@9.5.3: + version "9.5.3" + resolved "https://registry.yarnpkg.com/react-intersection-observer/-/react-intersection-observer-9.5.3.tgz#f47a31ed3a0359cbbfdb91a53d7470ac2ab7b3c7" + integrity sha512-NJzagSdUPS5rPhaLsHXYeJbsvdpbJwL6yCHtMk91hc0ufQ2BnXis+0QQ9NBh6n9n+Q3OyjR6OQLShYbaNBkThQ== + react-is@^16.10.2, react-is@^16.12.0, react-is@^16.13.1, react-is@^16.7.0: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" @@ -13835,10 +13840,10 @@ react-virtualized-auto-sizer@1.0.6: resolved "https://registry.yarnpkg.com/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.6.tgz#66c5b1c9278064c5ef1699ed40a29c11518f97ca" integrity sha512-7tQ0BmZqfVF6YYEWcIGuoR3OdYe8I/ZFbNclFlGOC3pMqunkYF/oL30NCjSGl9sMEb17AnzixDz98Kqc3N76HQ== -react-window@1.8.9: - version "1.8.9" - resolved "https://registry.yarnpkg.com/react-window/-/react-window-1.8.9.tgz#24bc346be73d0468cdf91998aac94e32bc7fa6a8" - integrity sha512-+Eqx/fj1Aa5WnhRfj9dJg4VYATGwIUP2ItwItiJ6zboKWA6EX3lYDAXfGF2hyNqplEprhbtjbipiADEcwQ823Q== +react-window@1.8.10: + version "1.8.10" + resolved "https://registry.yarnpkg.com/react-window/-/react-window-1.8.10.tgz#9e6b08548316814b443f7002b1cf8fd3a1bdde03" + integrity sha512-Y0Cx+dnU6NLa5/EvoHukUD0BklJ8qITCtVEPY1C/nL8wwoZ0b5aEw8Ff1dOVHw7fCzMt55XfJDd8S8W8LCaUCg== dependencies: "@babel/runtime" "^7.0.0" memoize-one ">=3.1.1 <6"