How to use Dynamic Routing to trigger the same .js in pages? - reactjs

I have multiple routes for e.g:
/solutions/
/solutions/web-development/
/features/
/features/flexbox/
/plugins/
/plugins/permalink/
and so on.
I would like to run the same file (abc.js) for all of these routes. I have checked the Dynamic Routing Section of Next.js but according to that section, My understanding is that I need to create multiple directories and copy the same file on multiple instances.
Is there any way by which I can run the single file for all the DEFINED routes or for the whole site?
EDIT: I know that there is a way to do that by creating Custom Server and manually add dynamic routes BUT I am looking to achieve this without the creation of the external server.

I have found a way to tackle this thing. This can be done using the next.config.js file. The only thing which you needed is the page URLs and then you can apply the same file or even add conditions to apply using multiple files.
Here is the sample code:
module.exports = {
exportPathMap: async function(
defaultPathMap,
{ dev, dir, outDir, distDir, buildId }
) {
const paths = {};
const pageURLs = [
'/solutions/',
'/solutions/web-development/',
'/features/',
'/features/flexbox/',
'/plugins/',
'/plugins/permalink/'
];
var loopInit = 0;
var loopCount = pageURLs.length;
var url = '';
for (loopInit = 0; loopInit < loopCount; loopInit += 1) {
url = pageURLs[loopInit];
switch(url) {
case '/solutions/':
paths[`${url}`] = {
page: '/solutions',
query: {
slug: url
}
};
break;
case '/features/':
paths[`${url}`] = {
page: '/features',
query: {
slug: url
}
};
break;
default:
paths[`${url}`] = {
page: '/',
query: {
slug: url
}
};
break;
}
}
return paths;
},
exportTrailingSlash: true
};
In the above example, I have hardcoded the URLs in pageURLs variable. You can pass dynamic values in it like get Permalinks from WordPress, URL Alias from Drupal or from any other CMS or Headless CMS, etc.
In the switch case, I am applying different templates on /solutions/ and /features/. For the remaining URLs, I am applying a single template.
NOTE: page: '/' refers index.js under pages directory similarly, page: '/solutions' refers solutions.js under pages directory and so on. It can be changed/vary as per developer choice.
I have tested this solution on the 9.1.4 version of Next.js. Please refer to the Next.js documentation for further details.
https://nextjs.org/docs#custom-configuration
https://nextjs.org/docs#usage
EDITED: This solution works for both server-side rendering and Next.js export.

Related

How to list all pages in a path?

I have a structure like this:
pages:
- route1
- lots of js page
- index.js
I would like to display a list of all pages under route1 on my index page.
How can I fetch all available pages?
I tried to use getStaticProps in index to load all the files using fs and path but I am not able to require all the pages.
export async function fetchPages() {
const fs = require('fs')
const path = require('path')
const files = fs.readdirSync(path.join(process.cwd(), '/pages/route1/'))
return map(files, (f) => {
return require(path.join(process.cwd(), '/pages/route1/', f))
})
}
but this is not working.
Edit: require is used to load all the export from those pages such as title of the page or excerpt to display on the index page.
Edit: The error is Error: Cannot find module '/path/to/pages/route1/pageName.js'. Coming from the require.
Edit: I tried to use How to generate a menu based on the files in the pages directory in Next.js but it does not work since in the next config file we have to use require/module.export but the require('path/to/page') is going to bring react pages with imports and exports
Can you create a page variable as an Array and push routes ?
const fs = require('fs')
const path = require('path')
const pages = []
const files = fs.readdirSync(path.join(process.cwd(), '/pages/route1/'))
files.forEach((file) => {
pages.push(require(path.join(process.cwd(), '/pages/route1/', file)))
})
return pages

Gatsby V4: How to implement gatsby-plugin-react-i18next for client only routes

I'm trying to implement client routes in Gatsby together with gatsby-plugin-react-i18next for two languages. I followed officel Gataby documentation and there is no client only path implementation explained.
Below is the code i implemeted.
gatsby-node.js
function langPrefix(page) {
return page.context.language === page.context.i18n.defaultLanguage &&
!page.context.i18n.generateDefaultLanguagePage
? ''
: `/${page.context.language}`
}
exports.onCreatePage = ({ page, actions }) => {
const { createPage } = actions
// Removing the ^ skips an optional /:lang prefix
if (page.path.match(/\/app/)) {
// adding lang if it's not the default page.
page.matchPath = `${langPrefix(page)}/app/*`
createPage(page)
}
}
Appjs
src/app/app.js
function App() {
return (
<>
<Router basepath="/:lang/app">
<PrivateRoute path="/accounthome" component={AccountHome} location=""/>
</Router>
<Router basepath="/app">
<PrivateRoute path="/accounthome" component={AccountHome} location=""/>
</Router>
</>)
}
export default App
Gatsby config
{
resolve: `gatsby-plugin-react-i18next`,
options: {
localeJsonSourceName: `locale`, // name given to `gatsby-source-filesystem` plugin.
languages: ["en", "fr"],
defaultLanguage: `en-us`,
fallbackLanguage: `en-us`,
// if you are using Helmet, you must include siteUrl, and make sure you add http:https
siteUrl: `https://my.costco.com/`,
ns: langTranslationConfig,
// you can pass any i18next options
i18nextOptions: {
interpolation: {
escapeValue: false // not needed for react as it escapes by default
},
nsSeparator: false
},
pages: [
{
matchPath: '/:lang/app/accounthome',
getLanguageFromPath: true,
excludeLanguages: ['en-ca']
},
{
matchPath: '/preview',
languages: ['en']
}
]
}
}
Router path : http://localhost:8000/en-us/app/accounthome
When am accessing this rote in browser This code show Gatsby.js development 404 page not found. Any pointer what am missing and am not sure how to access the translation contents in client only route page example account home page. Do i need to write the graph query in account home page or i dont need to ?
I think your regex is leaking your code. I guess it should look like:
if (page.path.match(/^\/app/)) {
page.matchPath = `${langPrefix(page)}/app/*`
createPage(page)
}
Either way, check the created page list by accessing the 404 page in development mode. By default, there should be a list of all created pages. Check the paths there to see if you can spot any mistakes or trailing slash issues.
The problem here is that your page is not being generated properly, that's why it throws a 404, so checking the created pages may help you to spot the mistake or at least, a thread to pull.
After a few research I've seen that you are basing your approach in: Gatsby can't find client routes when using gatsby-plugin-react-i18next
In their case, the langPrefix function is only prefixing the language to the page slug if it's the default one:
function langPrefix(page) {
return page.context.language === page.context.i18n.defaultLanguage &&
!page.context.i18n.generateDefaultLanguagePage
? ''
: `/${page.context.language}`
}
In your case, I'm not sure the plugin supports en-us (it's en-US according to https://github.com/microapps/gatsby-plugin-react-i18next/issues/100) and I think that's the reason why there's a leak in your page creation. Try using en instead of en-us or directly looking for en-US paths.

NextJS dynamimc routing question about slugs

I have a doubt with nextjs..
I'm building my site like this
pages
[slug]
index.jsx
index.jsx
so in my slug/index I'm doing this
export async function getStaticPaths() {
const resProducts = await fetch(`${process.env.PRIVATE_ENDPOINT}/products`);
const products = await resProducts.json();
const paths = products.data.map((p) => ({
params: {
slugProduct: p.slug,
},
}));
return {
// this should be dynamic
paths,
fallback: true,
};
}
My question is what happend if I add a new product in my back office?
Do I have to rebuild with next build?
My question is what happend if I add a new product in my back office?
Do I have to rebuild with next build?
The short answer is NO. If the requested page have not been genereted at build time, Next.js will serve a "fallback" version of the page and will statically generate the requested path HTML and JSON on the background. When the statically generation completed, the browser receives the JSON for the generated path. Subsequent requests to the same path will serve the generated page, just like other pages pre-rendered at build time.
Don't forget to use router.isFallback to detect that request is on fallback.
You can see the good document here.
https://nextjs.org/docs/basic-features/data-fetching#getstaticpaths-static-generation

Netlify deployment Cannot query field "allContentfulGallery" on type "Query"

I am creating an application on React.js, Gatsby.js, and Contentful. My Application is working fine on my local but when I deploy my app to Natilify Cannot query field "allContentfulGallery" on type "Query". And My GraphQl Queries are also working fine. Please help me I am very sticking by this error."allContentfulGallery" is my collection Name
Very thanks in advance
My gatsby-node.js configuration
const galleryResult = await graphql(`
query gallery {
allContentfulGallery {
edges {
node {
title
slug
images {
title
file {
url
}
}
sys {
contentType {
sys {
id
linkType
type
}
}
revision
type
}
}
}
}
}
`)
var galleryArr =
galleryResult &&
galleryResult.data &&
galleryResult.data.allContentfulGallery &&
galleryResult.data.allContentfulGallery.edges
galleryArr.forEach(edge => {
createPage({
path: `/gallery/${edge.node.slug}`,
component: galleryTemplate,
context: {
title: edge.node.title,
slug: edge.node.slug,
sys: {
...edge.node.sys,
},
},
})
})
It seems (according to the comments) that the environment variables are not properly set, since they work locally (under both environments, gatsby develop and gatsby build) but not on GitLab nor Netlify.
Dealing with Gatsby + Netlify requires to prefix all environment variables with GATSBY_ as you can see in Netlify docs:
Any environment variables prefixed with GATSBY_ are processed by
Gatsby and made available in the browser for client-side JavaScript
access. Visit the Gatsby docs about environment variables for more
information.
So, change all variables locally, and in Netlify's and GitLab dashboard prefixing them with GATSBY_.
CONTENTFUL_ENVIRONMENT
CONTENTFUL_API_KEY
CONTENTFUL_SPACE_ID
Will become:
GATSBY_CONTENTFUL_ENVIRONMENT
GATSBY_CONTENTFUL_API_KEY
GATSBY_CONTENTFUL_SPACE_ID
Keep in mind that this approach applies to all environment variables, not only for the Contentful ones.
Normally I'm pretty sure about the resolutions but in your case, if you haven't set the environment variables properly, the plugin configuration should fail, breaking the compilation before your issue prompts and it's not the case.

404 for all routes with included locale - NextJS with next-i18next

Hi I am following the docs from here: github docs
, but all URLs with locales return 404.
For the example:
localhost:3000/de/second-page = 404
localhost:3000/en/second-page = 404
localhost:3000/de = 404
localhost:3000/en = 404
same for the default locale.
localhost:3000/second-page = 200
localhost:3000 = 200
I guess, this is because there is no pages/de/second-page.js, for the example, but what's the purpose then of this library, if it doesn't solve this problem.
I have searched a lot and I know about localSubpaths, but seems that it doesn't work:
module.exports = new NextI18Next({
otherLanguages: ['fr'],
//localeSubpaths: localeSubpathVariations[localeSubpaths],
localeSubpaths: {
de: 'de',
en: 'en',
}
})
It doesn't work in my app, but it doesn't work in their sample, too: their sample
Have you checked these two steps ?
After creating and exporting your NextI18Next instance, you need to
take the following steps to get things working:
Create an _app.js file inside your pages directory, and wrap it with
the NextI18Next.appWithTranslation higher order component (HOC). You
can see this approach in the examples/simple/pages/_app.js. Your app
component must either extend App if it's a class component or define a
getInitialProps if it's a functional component (explanation here).
Create a next.config.js file inside your root directory if you want to
use locale subpaths. You can see this approach in the
examples/simple/next.config.js (Next.js 9.5+ required).
const { nextI18NextRewrites } = require('next-i18next/rewrites')
const localeSubpaths = {
de: 'de',
en: 'en',
};
module.exports = {
rewrites: async () => nextI18NextRewrites(localeSubpaths),
publicRuntimeConfig: {
localeSubpaths,
},
}

Resources