From 001230e0a889b17cb2ee92448ee8128d22d3cf67 Mon Sep 17 00:00:00 2001 From: Jimmy Merritello Date: Wed, 27 May 2020 16:22:33 -0500 Subject: [PATCH] Add Route as Modal Page Example (#12945) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### Add dynamic routes to _with-route-as-modal_ example This PR adds [dynamic routes](https://nextjs.org/docs/routing/dynamic-routes), [getStaticPaths](https://nextjs.org/docs/basic-features/data-fetching#getstaticpaths-static-generation), and [getStaticProps](https://nextjs.org/docs/basic-features/data-fetching#getstaticprops-static-generation) to the **with-route-as-modal** example. This change might also clear up some confusion here on https://github.com/zeit/next.js/issues/11971 Additionally this PR makes sure each modal route is also a modal **page.** This is an important distinction and makes sure the experience is the same should the URL (route) be shared as a link. In other words, `index.js` need not be the only "entrypoint" to browsing the website. With the additions in this PR, each post page is an actual page, so if you were to share the link for **Post 3** you'd get this: (clickable outer region brings you back to the 'gallery') **Update:** I have also included the `pathname` to signal the difference in which page component is rendered Rather than this (previously): I have used a similar approach [here 🔗](https://hashiconf.com/digital-june/schedule/the-hitchhikers-guide-to-terraform-your-infrastructure) --- examples/with-route-as-modal/README.md | 4 +- .../with-route-as-modal/app-styles.module.css | 5 +++ .../with-route-as-modal/components/Article.js | 11 +++++ .../with-route-as-modal/components/Grid.js | 28 ++++++++++++ .../with-route-as-modal/components/Post.js | 10 ++++- .../components/PostCard.js | 11 ----- .../styles.module.css} | 10 +---- examples/with-route-as-modal/pages/_app.js | 8 +++- .../pages/article/[articleId].js | 43 +++++++++++++++++++ examples/with-route-as-modal/pages/index.js | 12 ++---- .../pages/post/[postId].js | 2 +- 11 files changed, 109 insertions(+), 35 deletions(-) create mode 100644 examples/with-route-as-modal/app-styles.module.css create mode 100644 examples/with-route-as-modal/components/Article.js create mode 100644 examples/with-route-as-modal/components/Grid.js delete mode 100644 examples/with-route-as-modal/components/PostCard.js rename examples/with-route-as-modal/{style.css => components/styles.module.css} (83%) create mode 100644 examples/with-route-as-modal/pages/article/[articleId].js diff --git a/examples/with-route-as-modal/README.md b/examples/with-route-as-modal/README.md index 153de4913b..7babf934c9 100644 --- a/examples/with-route-as-modal/README.md +++ b/examples/with-route-as-modal/README.md @@ -1,8 +1,8 @@ # with-route-as-modal -On many popular social media, opening a post will update the URL but won't trigger a navigation and will instead display the content inside a modal. This behavior ensure the user won't lose the current UI context (scroll position). The URL still reflect the post's actual page location and any refresh will bring the user there. This behavior ensure great UX without neglecting SEO. +On many popular social media, opening a post will update the URL but won't trigger a navigation and will instead display the content inside a modal. This behavior ensures the user won't lose the current UI context (scroll position). The URL still reflect the post's actual page location and any refresh will bring the user there. This behavior ensures great UX without neglecting SEO. -This example show how to conditionally display a modal based on a route. +This example shows how to conditionally display a modal based on a route. ## Deploy your own diff --git a/examples/with-route-as-modal/app-styles.module.css b/examples/with-route-as-modal/app-styles.module.css new file mode 100644 index 0000000000..2c5ccd2dc8 --- /dev/null +++ b/examples/with-route-as-modal/app-styles.module.css @@ -0,0 +1,5 @@ +.content { + display: flex; + justify-content: center; + align-items: center; +} diff --git a/examples/with-route-as-modal/components/Article.js b/examples/with-route-as-modal/components/Article.js new file mode 100644 index 0000000000..dc62025edc --- /dev/null +++ b/examples/with-route-as-modal/components/Article.js @@ -0,0 +1,11 @@ +import styles from './styles.module.css' + +const Post = ({ id, pathname }) => { + return ( +
+ I am the article {id}; my pathname is: {pathname} +
+ ) +} + +export default Post diff --git a/examples/with-route-as-modal/components/Grid.js b/examples/with-route-as-modal/components/Grid.js new file mode 100644 index 0000000000..03bcfe53d7 --- /dev/null +++ b/examples/with-route-as-modal/components/Grid.js @@ -0,0 +1,28 @@ +import Link from 'next/link' +import styles from './styles.module.css' + +export const data = [1, 2, 3, 4, 5, 6, 7, 8, 9] + +export default function PostCardGrid() { + return ( +
+

With QueryString Routing, and a reload won't use the modal

+
+ {data.map((id, index) => ( + + {id} + + ))} +
+ +

With Dynamic Routing, and reloads will keep the modal

+
+ {data.map((id, index) => ( + + {id} + + ))} +
+
+ ) +} diff --git a/examples/with-route-as-modal/components/Post.js b/examples/with-route-as-modal/components/Post.js index c98c03425a..361011f047 100644 --- a/examples/with-route-as-modal/components/Post.js +++ b/examples/with-route-as-modal/components/Post.js @@ -1,5 +1,11 @@ -const Post = ({ id }) => { - return
{`I am the post ${id}`}
+import styles from './styles.module.css' + +const Post = ({ id, pathname }) => { + return ( +
+ I am the post {id}; my pathname is: {pathname} +
+ ) } export default Post diff --git a/examples/with-route-as-modal/components/PostCard.js b/examples/with-route-as-modal/components/PostCard.js deleted file mode 100644 index dd8700fcc6..0000000000 --- a/examples/with-route-as-modal/components/PostCard.js +++ /dev/null @@ -1,11 +0,0 @@ -import Link from 'next/link' - -const PostCard = ({ id }) => { - return ( - - {id} - - ) -} - -export default PostCard diff --git a/examples/with-route-as-modal/style.css b/examples/with-route-as-modal/components/styles.module.css similarity index 83% rename from examples/with-route-as-modal/style.css rename to examples/with-route-as-modal/components/styles.module.css index 57f92d1d4f..64bf923386 100644 --- a/examples/with-route-as-modal/style.css +++ b/examples/with-route-as-modal/components/styles.module.css @@ -1,12 +1,6 @@ -body { - margin: 0; -} - -#__next { +.postCardGridWrapper { display: flex; - justify-content: center; - align-items: center; - height: 100vh; + flex-direction: column; } .postCardGrid { diff --git a/examples/with-route-as-modal/pages/_app.js b/examples/with-route-as-modal/pages/_app.js index e94667d6f6..1da7d90e1e 100644 --- a/examples/with-route-as-modal/pages/_app.js +++ b/examples/with-route-as-modal/pages/_app.js @@ -1,7 +1,11 @@ -import '../style.css' +import styles from '../app-styles.module.css' function MyApp({ Component, pageProps }) { - return + return ( +
+ +
+ ) } export default MyApp diff --git a/examples/with-route-as-modal/pages/article/[articleId].js b/examples/with-route-as-modal/pages/article/[articleId].js new file mode 100644 index 0000000000..671aad5dd9 --- /dev/null +++ b/examples/with-route-as-modal/pages/article/[articleId].js @@ -0,0 +1,43 @@ +import { useEffect } from 'react' +import { useRouter } from 'next/router' +import Modal from 'react-modal' +import Article from '../../components/Article' +import { data } from '../../components/Grid' + +Modal.setAppElement('#__next') + +const ArticlePage = ({ articleId }) => { + const router = useRouter() + + useEffect(() => { + router.prefetch('/') + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []) + + return ( + <> + router.push('/')} + contentLabel="Post modal" + > +
+ + + ) +} + +export default ArticlePage + +export function getStaticProps({ params: { articleId } }) { + return { props: { articleId: articleId } } +} + +export function getStaticPaths() { + return { + paths: data.map((articleId) => ({ + params: { articleId: articleId.toString() }, + })), + fallback: false, + } +} diff --git a/examples/with-route-as-modal/pages/index.js b/examples/with-route-as-modal/pages/index.js index 049989abb6..33d35861b4 100644 --- a/examples/with-route-as-modal/pages/index.js +++ b/examples/with-route-as-modal/pages/index.js @@ -1,12 +1,10 @@ import { useRouter } from 'next/router' import Modal from 'react-modal' import Post from '../components/Post' -import PostCard from '../components/PostCard' +import Grid from '../components/Grid' Modal.setAppElement('#__next') -const posts = [1, 2, 3, 4, 5, 6, 7, 8, 9] - const Index = () => { const router = useRouter() @@ -17,13 +15,9 @@ const Index = () => { onRequestClose={() => router.push('/')} contentLabel="Post modal" > - + -
- {posts.map((id, index) => ( - - ))} -
+ ) } diff --git a/examples/with-route-as-modal/pages/post/[postId].js b/examples/with-route-as-modal/pages/post/[postId].js index 696f4ea71f..37aca1d099 100644 --- a/examples/with-route-as-modal/pages/post/[postId].js +++ b/examples/with-route-as-modal/pages/post/[postId].js @@ -5,7 +5,7 @@ const PostPage = () => { const router = useRouter() const { postId } = router.query - return + return } export default PostPage