From 8b6bffcff2ab612cf7900552043a85deb148b435 Mon Sep 17 00:00:00 2001 From: Ren Amamiya <123083837+reyamir@users.noreply.github.com> Date: Sun, 23 Apr 2023 08:25:27 +0700 Subject: [PATCH] fixed ssr errors --- src/components/appHeader/actions.tsx | 25 ++++++--- src/components/channels/channelListItem.tsx | 2 +- src/components/chats/chatList.tsx | 2 +- src/components/eventCollector.tsx | 12 ++++- src/components/note/preview/video.tsx | 2 +- .../{index.page.tsx => index.page.client.tsx} | 0 .../{index.page.tsx => index.page.client.tsx} | 0 src/pages/index.page.tsx | 6 ++- .../{index.page.tsx => index.page.client.tsx} | 0 .../onboarding/login/step-2/index.page.tsx | 52 ++++++++++++------- src/renderer/_default.page.client.tsx | 18 +++++-- src/renderer/_default.page.server.tsx | 21 +++++--- src/utils/transform.tsx | 1 + vite.config.ts | 5 ++ 14 files changed, 101 insertions(+), 45 deletions(-) rename src/pages/channel/{index.page.tsx => index.page.client.tsx} (100%) rename src/pages/chat/{index.page.tsx => index.page.client.tsx} (100%) rename src/pages/newsfeed/following/{index.page.tsx => index.page.client.tsx} (100%) diff --git a/src/components/appHeader/actions.tsx b/src/components/appHeader/actions.tsx index f5c4cf0d..df14a387 100644 --- a/src/components/appHeader/actions.tsx +++ b/src/components/appHeader/actions.tsx @@ -1,6 +1,5 @@ -import { platform } from '@tauri-apps/api/os'; import { ArrowLeft, ArrowRight, Refresh } from 'iconoir-react'; -import { useLayoutEffect, useState } from 'react'; +import { useCallback, useEffect, useState } from 'react'; export default function AppActions() { const [os, setOS] = useState(''); @@ -17,13 +16,23 @@ export default function AppActions() { window.location.reload(); }; - useLayoutEffect(() => { - const getPlatform = async () => { - const result = await platform(); - setOS(result); - }; + const getPlatform = useCallback(async () => { + const { platform } = await import('@tauri-apps/api/os'); + const result = await platform(); - getPlatform().catch(console.error); + setOS(result); + }, []); + + useEffect(() => { + let ignore = false; + + if (!ignore) { + getPlatform().catch(console.error); + } + + return () => { + ignore = true; + }; }, []); return ( diff --git a/src/components/channels/channelListItem.tsx b/src/components/channels/channelListItem.tsx index 4b8368e9..3818f87d 100644 --- a/src/components/channels/channelListItem.tsx +++ b/src/components/channels/channelListItem.tsx @@ -7,7 +7,7 @@ export const ChannelListItem = ({ data }: { data: any }) => { return (
diff --git a/src/components/chats/chatList.tsx b/src/components/chats/chatList.tsx index 65bbacf1..b4b46dd4 100644 --- a/src/components/chats/chatList.tsx +++ b/src/components/chats/chatList.tsx @@ -11,7 +11,7 @@ import { useEffect, useState } from 'react'; export default function ChatList() { const [list, setList] = useState([]); const [activeAccount]: any = useLocalStorage('account', {}); - const profile = JSON.parse(activeAccount.metadata); + const profile = activeAccount.metadata ? JSON.parse(activeAccount.metadata) : null; useEffect(() => { let ignore = false; diff --git a/src/components/eventCollector.tsx b/src/components/eventCollector.tsx index e402d962..f640e047 100644 --- a/src/components/eventCollector.tsx +++ b/src/components/eventCollector.tsx @@ -13,7 +13,7 @@ import { useCallback, useContext, useEffect, useRef } from 'react'; export default function EventCollector() { const [pool, relays]: any = useContext(RelayContext); - const [activeAccount]: any = useLocalStorage('account', {}); + const [activeAccount]: any = useLocalStorage('account', null); const setHasNewerNote = useSetAtom(hasNewerNoteAtom); const follows = JSON.parse(activeAccount.follows); @@ -106,7 +106,15 @@ export default function EventCollector() { }, [activeAccount.pubkey, activeAccount.id, follows, pool, relays, setHasNewerNote]); useEffect(() => { - subscribe(); + let ignore = false; + + if (!ignore) { + subscribe(); + } + + return () => { + ignore = true; + }; }, [setHasNewerNote, subscribe]); return ; diff --git a/src/components/note/preview/video.tsx b/src/components/note/preview/video.tsx index 138e14ed..89dec265 100644 --- a/src/components/note/preview/video.tsx +++ b/src/components/note/preview/video.tsx @@ -1,5 +1,5 @@ import { memo } from 'react'; -import ReactPlayer from 'react-player/lazy'; +import ReactPlayer from 'react-player'; export const VideoPreview = memo(function VideoPreview({ url }: { url: string }) { return ( diff --git a/src/pages/channel/index.page.tsx b/src/pages/channel/index.page.client.tsx similarity index 100% rename from src/pages/channel/index.page.tsx rename to src/pages/channel/index.page.client.tsx diff --git a/src/pages/chat/index.page.tsx b/src/pages/chat/index.page.client.tsx similarity index 100% rename from src/pages/chat/index.page.tsx rename to src/pages/chat/index.page.client.tsx diff --git a/src/pages/index.page.tsx b/src/pages/index.page.tsx index 299aea41..3f618f28 100644 --- a/src/pages/index.page.tsx +++ b/src/pages/index.page.tsx @@ -18,7 +18,7 @@ import LumeSymbol from '@assets/icons/Lume'; import { writeStorage } from '@rehooks/local-storage'; import { useCallback, useContext, useEffect, useRef } from 'react'; -import { navigate } from 'vite-plugin-ssr/client/router'; +import { navigate, prefetch } from 'vite-plugin-ssr/client/router'; export function Page() { const [pool, relays]: any = useContext(RelayContext); @@ -123,7 +123,8 @@ export function Page() { () => { updateLastLogin(dateToUnix(now.current)); timeout.current = setTimeout(() => { - navigate('/newsfeed/following', { overwriteLastHistoryEntry: true }); + prefetch('/newsfeed/following'); + navigate('/newsfeed/following'); }, 5000); }, { @@ -152,6 +153,7 @@ export function Page() { // fetch data fetchData(account, account.follows); } else { + prefetch('/onboarding'); navigate('/onboarding', { overwriteLastHistoryEntry: true }); } }) diff --git a/src/pages/newsfeed/following/index.page.tsx b/src/pages/newsfeed/following/index.page.client.tsx similarity index 100% rename from src/pages/newsfeed/following/index.page.tsx rename to src/pages/newsfeed/following/index.page.client.tsx diff --git a/src/pages/onboarding/login/step-2/index.page.tsx b/src/pages/onboarding/login/step-2/index.page.tsx index 5e52b89d..ce3a3b6e 100644 --- a/src/pages/onboarding/login/step-2/index.page.tsx +++ b/src/pages/onboarding/login/step-2/index.page.tsx @@ -10,20 +10,22 @@ import { createAccount, createPleb, updateAccount } from '@utils/storage'; import { nip02ToArray } from '@utils/transform'; import { getPublicKey } from 'nostr-tools'; -import { useCallback, useContext, useEffect, useRef, useState } from 'react'; +import { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'; +import { navigate } from 'vite-plugin-ssr/client/router'; export function Page() { const pageContext = usePageContext(); const searchParams = pageContext.urlParsed.search; const privkey = searchParams.privkey; - const pubkey = getPublicKey(privkey); + const pubkey = useMemo(() => getPublicKey(privkey), [privkey]); const [pool, relays]: any = useContext(RelayContext); const [profile, setProfile] = useState({ metadata: null }); const [done, setDone] = useState(false); const timeout = useRef(null); + const nip02 = useRef(null); const createPlebs = useCallback(async (tags: string[]) => { for (const tag of tags) { @@ -33,6 +35,16 @@ export function Page() { } }, []); + const submit = () => { + // update account's folllows with NIP-02 tag list + const arr = nip02ToArray(nip02.current); + updateAccount('follows', arr, pubkey); + // create plebs (saved nostr profile) + createPlebs(nip02.current); + // redirect to splashscreen + navigate('/', { overwriteLastHistoryEntry: true }); + }; + useEffect(() => { const unsubscribe = pool.subscribe( [ @@ -43,20 +55,20 @@ export function Page() { ], relays, (event: any) => { - if (event.kind === 0) { - // create account - createAccount(pubkey, privkey, event.content); - // update state - setProfile({ - metadata: JSON.parse(event.content), - }); - } else { - if (event.tags.length > 0) { - createPlebs(event.tags); - const arr = nip02ToArray(event.tags); - // update account's folllows with NIP-02 tag list - updateAccount('follows', arr, pubkey); - } + switch (event.kind) { + case 0: + // create account + createAccount(pubkey, privkey, event.content); + // update state + setProfile({ + metadata: JSON.parse(event.content), + }); + break; + case 3: + nip02.current = event.tags; + break; + default: + break; } }, undefined, @@ -73,7 +85,7 @@ export function Page() { unsubscribe(); clearTimeout(timeout.current); }; - }, [pool, relays, pubkey, privkey, createPlebs]); + }, [pool, relays, pubkey, privkey]); return ( @@ -128,12 +140,12 @@ export function Page() { > ) : ( - submit()} className="inline-flex w-full transform items-center justify-center rounded-lg bg-gradient-to-r from-fuchsia-300 via-orange-100 to-amber-300 px-3.5 py-2.5 font-medium text-zinc-800 active:translate-y-1 disabled:cursor-not-allowed disabled:opacity-30" > Done! Go to newsfeed - + )}
diff --git a/src/renderer/_default.page.client.tsx b/src/renderer/_default.page.client.tsx index a82fd1b7..daaefcef 100644 --- a/src/renderer/_default.page.client.tsx +++ b/src/renderer/_default.page.client.tsx @@ -2,19 +2,31 @@ import '@renderer/index.css'; import { Shell } from '@renderer/shell'; import { PageContextClient } from '@renderer/types'; -import { hydrateRoot } from 'react-dom/client'; +import { Root, createRoot, hydrateRoot } from 'react-dom/client'; export const clientRouting = true; +let root: Root; export async function render(pageContext: PageContextClient) { const { Page, pageProps } = pageContext; if (!Page) throw new Error('Client-side render() hook expects pageContext.Page to be defined'); - hydrateRoot( - document.getElementById('app')!, + const page = ( ); + + const container = document.getElementById('app'); + // SPA + if (container.innerHTML === '' || !pageContext.isHydration) { + if (!root) { + root = createRoot(container); + } + root.render(page); + // SSR + } else { + root = hydrateRoot(container, page); + } } diff --git a/src/renderer/_default.page.server.tsx b/src/renderer/_default.page.server.tsx index 79018e03..a5e69201 100644 --- a/src/renderer/_default.page.server.tsx +++ b/src/renderer/_default.page.server.tsx @@ -7,15 +7,22 @@ import { dangerouslySkipEscape, escapeInject } from 'vite-plugin-ssr/server'; export const passToClient = ['pageProps']; export function render(pageContext: PageContextServer) { - const { Page, pageProps } = pageContext; + let pageHtml: string; - if (!Page) throw new Error('My render() hook expects pageContext.Page to be defined'); + if (!pageContext.Page) { + // SPA + pageHtml = ''; + } else { + // SSR / HTML-only + const { Page, pageProps } = pageContext; + if (!Page) throw new Error('My render() hook expects pageContext.Page to be defined'); - const pageHtml = ReactDOMServer.renderToString( - - - - ); + pageHtml = ReactDOMServer.renderToString( + + + + ); + } return escapeInject` diff --git a/src/utils/transform.tsx b/src/utils/transform.tsx index b1f853d9..a2cf3921 100644 --- a/src/utils/transform.tsx +++ b/src/utils/transform.tsx @@ -6,6 +6,7 @@ export const nip02ToArray = (tags: string[]) => { tags.forEach((item) => { arr.push(item[1]); }); + return arr; }; diff --git a/vite.config.ts b/vite.config.ts index b78d40d1..5fa66fa7 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -5,4 +5,9 @@ import viteTsconfigPaths from 'vite-tsconfig-paths'; export default defineConfig({ plugins: [react(), ssr({ prerender: true }), viteTsconfigPaths()], + define: { + global: { + window: {}, + }, + }, });