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
Related
I am trying to send a function as one of the value from a remix route loader function
export const loader: LoaderFunction = async ({ request }) => {
const userId = await requireUserId(request)
const user = await getUserById(userId)
const canUserPerformAction = getUserPermissions(user)
const organisations = await Organisation.find({}).exec()
return {
organisations,
canUserPerformAction
}
}
getUserPermissions(user) returns a function with the current user context, which needs to be used in the frontend.
this function always ends up being undefined when I fetch it using useLoaderData() in the default component/ frontend. Is there a better way to do this?
Your loader can either be called during the whole page generation, or using an XHR when navigating in your app.
Your loader have to return a valid Response object, which will usually be a JSON response : https://remix.run/docs/en/v1/api/conventions#returning-response-instances
In your code sample, the returned object is automatically converted to a JSON string, and since functions aren't valid json, it gets stripped.
You will need to call your canUserPerformAction and return its actual result as JSON.
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.
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,
}
}
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
I'm having a problem with getServerSideProps in NextJS not updating values on page load. It seems to be having the same effect as using getStaticProps when calling from data that is an imported JSON file.
Here's the applicable code:
/update/[...id].js
import { hasPermission, getPermissions } from '../../lib/permissions'
...
//in the page function I use the ternary to check permission of the user
{ (hasPermission(session.user.email, `${params.id[0]}-edit`, permissions)) ? <HasPerm /> : <NoPerm /> }
...
export async function getServerSideProps(context) {
const params = context.query
const permissions = getPermissions()
return {
props: { params, permissions }
}
}
/lib/permissions.js
import permissions from '../db/users.json'
export function hasPermission(username, group, perm = false) {
if (!perm)
perm = permissions
if (username in perm && perm[username].groups.includes(group)) {
return true
}
if (perm.all.groups.includes(group)) {
return true
}
return false
}
export function getPermissions() {
return permissions
}
For SSR pages that were understandably doing this to begin with, I pass in the permissions to the page in getStaticProps and pass those values into my hasPermission() function in those pages so that they are revalidated on permissions change. Yet there is no revalidation option in getServerSideProps so the data is not revalidated at all. I was using getInitialProps before but pretty much everyone discourages that because it disables ASO.
How do I use getServerSideProps such that my imported json is at least revalidated?
I ended up not using the json import and used fs instead for other reasons but the issue is resolved by using dynamic imports in the getServerSideProps:
export async function getServerSideProps(context) {
const permissions = await import('../db/users.json')
}
Also don't make my same mistake of passing the whole permissions database to every user as was being done by using a function like getPermissions in getStaticProps to get the data to the hasPermission function in the page. Instead, only serve data with getServerSideProps if the user has permission. In other words, ensure you're holding the data back from the server-side. Then you can also pass through an individual's permissions to the page if you need to, like for displaying a message saying you don't have permission.