Next.js Dynamic Route With a User Inputted URL - javascript

I am using the Next.js Router to enable different dashboards depending on the URL slug. This works when a button with the link is clicked, as the link passes the information to the Next.js Router, but it does not work when a URL is inputted directly into the browser (i.e. it does not work if the user refreshes the page, or just types the URL with the slug directly). So, while I am able to use dynamic routes when links are pressed, how can I enable dynamic routes when a link is not pressed?
The relevant code is below. Thank you very much
const dashboard = () => {
const router = useRouter();
const {dashboardID} = router.query;
return (
<Dashboard dashboardID = {dashboardID}/>
);
}
export default dashboard

On pagination the query already loaded on the context/custom hook.
You need to wait until router fully loads
const dashboard = () => {
const router = useRouter();
const {dashboardID} = router.query;
if(!dashboardID) return null //Wait until query with dashboardID loads to avoid undefined errors
return (
<Dashboard dashboardID = {dashboardID}/>
);
}
export default dashboard

Related

Routing to page A or Page B based on API response

I am stuck on an issue. Let's say I have a home page. From this home page, I want to route to either page A or page B.
I have a list of items on the home page and what I need to do is when I click on any item in the list, it makes a GET API call, and based on one field in the response which is a boolean, I either need to redirect to page A or page B.
Basically, I need to call an API on the click of the item and get the response before it is routed to either Page A or Page B.
Many thanks in advance
if you're using Next.JS, use useRouter prop to achieve this.
for example
import {useRouter} from "next/router";
export default function Page() {
const router = useRouter()
async function route() {
let res = await apiFunctionCall();
if (res) {
await router.replace({
pathname: '/page1'
})
} else {
await router.replace({
pathname: 'page2'
})
}
}
}
The closest solution I could get is to create a Lazy loaded component which calls the API and then based on the response, routes to either page A or Page B.
Before routing to the correct page based on the data that has been returned, the data first needs to be stored in a variable. The data will be stored in the res variable. The if else statement will then route to either page A or B based on the data.
<code>const Response = res.data;
if(Response.type === 'A'){
this.props.history.push('/page-a');
} else {
this.props.history.push('/page-b');
}
</code>

404 on new posts, after build-time, using Next.js and Sanity.io

My goal is to be able to add new posts the CMS(Sanity.io) after build-time, and for the site to be able to display received data on a provided slug using dynamic routes.
Everything works well in dev environment, but in production it seems the page can't use the new slugs provided from the CMS, and responds with a 404.
Here's my code getting the posts from the CMS, inside my [slug].tsx file.
[slug.tsx]
export const getStaticPaths: GetStaticPaths = async () => {
const query = `
*[_type=='post']{
_id,
slug {
current
}
}`
const posts = await sanityClient.fetch(query)
const paths = posts.map((post: Post) => ({
params: {
slug: post.slug.current,
},
}))
return {
paths,
fallback: 'blocking',
}
}
export const getStaticProps: GetStaticProps = async ({ params }) => {
const query = `
*[_type=='post' && slug.current == $slug][0]{
_id,
publishedAt,
title,
description,
mainImage,
gallery[0]->{
title,
link,
images,
display,
},
slug,
body
}`
const post = await sanityClient.fetch(query, { slug: params?.slug })
return {
props: {
post,
},
revalidate: 10,
}
}
When I add new posts in the CMS I immediately see the thumbnail come up on the website, with the correct image and other data, but when I click the thumbnail I get 404.
I hope someone can help me!
A dirty-quick fix: re-deploy your front end code (your nextjs app). In my case, I just commit a new change which triggers the building and deployment. And you will see your new page data of the slug.
But I believe there must be a solid solution. I thing it has something to do with 'Incremental Static Regeneration' in NextJS. But even I add revalidate: 10 to the getStaticProps(), it doesn't seem to work. Hope someone else could provide some tips on such issue.
You should be using getServerSideProps instead since you want new blog posts in Sanity to show up on your production as soon as it's published and not on every build.

Add id also in dynamic URLs like in stack overflows URLs

I had some alert components when each clicked; it will get redirected to a page
<div className="question11">
{data.map((itm) => (
<Link
key={itm._id}
href={{
pathname: "/[itm]",
query: { id: itm._id },
}}
as={`/${encodeURIComponent(
itm.Name.replace(/[^a-zA-Z0-9 - _ . ~]/g, "").replace(
/ /g,
"-"
)
)}`}
>
<Alert className="question13">{itm.Name}</Alert>
</Link>
))}
</div>
The redirected page has a URL in the following pattern
http://localhost:3000/itm.Name. Example: http://localhost:3000/spiderman-no-way-home-release-date-in-india. I am passing itm._id for accessing the corresponding data on the redirected page
export async function getServerSideProps(context) {
var id1 = context.query.id;
// console.log(context.query.id);
const queryRequest = fetch("https://askover.wixten.com/questone/" + id1).then(
async (res) => await res.json()
);
When I click on alert components, I can pass the itm._id, and the page is redirected properly. The issue occurs when I manually enter the URL in the browser.The issue here is not getting the itm._id from the alert component. The answer that I came up with here is to create an API to access the API by passing the itm.Name, but that will require deconstructing the itm.Name to its original form, and itm.Name might not be unique every time is there another method by which I can access itm._id itself also, if I can use the URL in http://localhost:3000/itm._id/itm.Name
this format also, I think it will be okay just as StackOverflow does it.
When you refresh the page you will lose the context, even if you use some store(local, session, etc) that will not work for the user visiting your app for the first time.
One thing always remains is URL, neither storage nor context.
To solve this kind of issue, what you can do is pass the id and slug parameters to the URL and read whenever requires.
Check more details here
Next.js Directory
pages
index.js
[id]
[slug].js
The URL will look something like this: https://localhost:3000/123/my-post-slug
, Slug is optional, It'll help for SEO purposes.
[slug].js
const Component = (props) => (
<div>
<h1>{props.title}</h1>
<p>{props.content}</p>
</div>
);
export async function getServerSideProps(context) {
const id = context.params.id;
const data = fetch(`https://askover.wixten.com/questone/${id}`).then((res) => await res.json());
return {
props: data,
}
}

query is empty when language is change using setAppLanguage in nextjs

I'm using Nextjs, and when I redirect to a page(pages/search/index), I can get the query in getServerSideProps but when I change the language using setAppLanguage by importing it from next-translate/setLanguage, the search page is reloaded again but the query is empty in getServerSideProps and I request with an empty query inside this page. By the way, the URL is updated from http://localhost:3000/tr/search?q=anything to http://localhost:3000/en/search?q=anything after the language is changed
It helped me
const router = useRouter()
const changeLanguage = (lang: string) => async () => {
await router.push(router.asPath, undefined, {
locale: lang
})
}
used it instead of setLanguage

Next.js: getStaticPaths for dynamic route with catching all routes [[...slug]].js

I read the docs of dynamic routes but they didn't explain much about how dynamic routes will work with "catching all routes".
My folder structure for this route is:
└──pages
└──catalog
└──[[...slug]].js
Here's my code:
export default function Catalog(props) {
return (
<Product product={props.product} />
)
}
export async function getStaticProps({ params }) {
const productSlug = params.slug[params.slug.length-1];
const data = await getSingleProduct(productSlug)
return {
props: {
product: data.product,
},
revalidate: 30
}
}
My API is WP and I have product pages URI like this /catalog/category/sub-category/product/
So if I go to the URL /catalog/category/sub-category/product/ it works fine with the code I shared below because I have const productSlug = params.slug[params.slug.length-1]; which will get my slug which I can pass to the API and use the product data just fine.
But I want to work with categories too, so if I go to /catalog/category/sub-category/ it should load the category page, and if I go to /catalog/category/ it should load up that category page.
Even this will work with the code I have because I'm getting the last element of params array which is the product slug, but that's NOT always the case. Sometimes the product is without any sub-category so the URI would be /catalog/category/product which means I can't fix it to the third element of the array and use the other two as category slugs.
The params gives me an array without any key or anything and I can't seem to figure out how to achieve this in next.js
Any help is appreciated!

Categories