From 43ae248e877d7ab648ac75672f454bc1b107294e Mon Sep 17 00:00:00 2001 From: Matchu Date: Wed, 14 Sep 2022 22:16:39 -0700 Subject: [PATCH] Migrate /items/[itemId] to Next routing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The tricky part here was that `returnPartialData` seems to behave differently during SSR. On the page itself, this seems to cause us to always get back at least an empty object, but in SSR we can sometimes get null—which means that a LOT of code that expects the item object to exist while in loading state gets thrown off. To keep this situation maximally clear, I added a bunch of null handling with `?.` to `ItemPageLayout`. An alternative would have been to check for null and put in an empty object if not, but this feels more resilient and more true to the situation. The search bar here is a bit tricky, but is pretty straightforwardly adapted from how we did the layouts in App.js. Fingers crossed that it works as smoothly as expected when the search page is migrated too! (Right now typing in there is all messy because it hops over to the fallback route and does its whole separate thing.) --- pages/items/[itemId].tsx | 19 ++++++ src/app/App.js | 7 -- src/app/GlobalFooter.js | 4 +- src/app/ItemPage.js | 75 ++++++++++++--------- src/app/ItemPageLayout.js | 36 +++++----- src/app/components/ItemCard.js | 17 +++-- src/app/components/ItemSearchPageToolbar.js | 33 ++++----- 7 files changed, 113 insertions(+), 78 deletions(-) create mode 100644 pages/items/[itemId].tsx diff --git a/pages/items/[itemId].tsx b/pages/items/[itemId].tsx new file mode 100644 index 0000000..b6ff963 --- /dev/null +++ b/pages/items/[itemId].tsx @@ -0,0 +1,19 @@ +import ItemSearchPageToolbar from "../../src/app/components/ItemSearchPageToolbar"; +import ItemPage from "../../src/app/ItemPage"; +import PageLayout from "../../src/app/PageLayout"; +import type { NextPageWithLayout } from "../_app"; + +const ItemPageWrapper: NextPageWithLayout = () => { + return ; +}; + +ItemPageWrapper.layoutComponent = ({ children }) => { + return ( + + + {children} + + ); +}; + +export default ItemPageWrapper; diff --git a/src/app/App.js b/src/app/App.js index 4ac5e0e..1c43968 100644 --- a/src/app/App.js +++ b/src/app/App.js @@ -13,7 +13,6 @@ import { loadable } from "./util"; const HomePage = loadable(() => import("./HomePage")); const ItemSearchPage = loadable(() => import("./ItemSearchPage")); -const ItemPage = loadable(() => import("./ItemPage")); const ItemTradesOfferingPage = loadable(() => import("./ItemTradesPage").then((m) => m.ItemTradesOfferingPage) ); @@ -67,12 +66,6 @@ function App() { - - - - - - diff --git a/src/app/GlobalFooter.js b/src/app/GlobalFooter.js index 259ec07..e9ae882 100644 --- a/src/app/GlobalFooter.js +++ b/src/app/GlobalFooter.js @@ -114,11 +114,11 @@ function ColorModeButton() { function useClassicDTIUrl() { const { pathname, query } = useRouter(); - if (pathname === "/items/:itemId") { + if (pathname === "/items/[itemId]") { return `https://impress.openneo.net/items/${query.itemId}`; } - if (pathname === "/user/:userId/lists") { + if (pathname === "/user/[userId]/lists") { return `https://impress.openneo.net/user/${query.userId}/closet`; } diff --git a/src/app/ItemPage.js b/src/app/ItemPage.js index ae6e6b7..8584b7b 100644 --- a/src/app/ItemPage.js +++ b/src/app/ItemPage.js @@ -33,7 +33,7 @@ import { import { MdPause, MdPlayArrow } from "react-icons/md"; import gql from "graphql-tag"; import { useQuery, useMutation } from "@apollo/client"; -import { Link, useParams } from "react-router-dom"; +import Link from "next/link"; import ItemPageLayout, { SubtleSkeleton } from "./ItemPageLayout"; import { @@ -58,10 +58,11 @@ import useCurrentUser from "./components/useCurrentUser"; import SpeciesFacesPicker, { colorIsBasic, } from "./ItemPage/SpeciesFacesPicker"; +import { useRouter } from "next/router"; function ItemPage() { - const { itemId } = useParams(); - return ; + const { query } = useRouter(); + return ; } /** @@ -69,7 +70,7 @@ function ItemPage() { * entry point for ItemPageDrawer! When embedded in ItemPageDrawer, the * `isEmbedded` prop is true, so we know not to e.g. set the page title. */ -export function ItemPageContent({ itemId, isEmbedded }) { +export function ItemPageContent({ itemId, isEmbedded = false }) { const { isLoggedIn } = useCurrentUser(); const { error, data } = useQuery( @@ -706,30 +707,31 @@ function ItemPageTradeLinks({ itemId, isEmbedded }) { function ItemPageTradeLink({ href, count, label, colorScheme, isEmbedded }) { return ( - + + ); } @@ -1149,9 +1151,8 @@ function CustomizeMoreButton({ speciesId, colorId, pose, itemId, isDisabled }) { const backgroundColorHover = useColorModeValue(undefined, "blackAlpha.900"); return ( - + ); } +function LinkOrButton({ href, ...props }) { + if (href != null) { + return ( + +