gvergnaud / nextjs-dynamic-routes Goto Github PK
View Code? Open in Web Editor NEW[Deprecated] Super simple way to create dynamic routes with Next.js
License: MIT License
[Deprecated] Super simple way to create dynamic routes with Next.js
License: MIT License
Thank you for the library. I'm trying to add an optional query param to handle pagination:
/search/keywords/foo?page=2
and my route looks like this:
router.add({ name: 'search-keywords', pattern: '/search/keywords/:keywords'})
Currently, the Link component does not check that you have correctly passed any expected path params:
import React from 'react'
import { Link } from '../routes'
export default () => (
<>
<Link route="character" id="1"><a>Luke Skywalker</a></Link>
<Link route="character"><a>C-3PO</a></Link> {/* Missing 'id' prop won't throw an error */}
</>
)
I think that an error should be thrown to if the developer forgets to pass in the correct prop to save time debugging later down the track. In the above example, the id
prop should be checked, and if it isn't passed into the Link
component, an error should be thrown.
I'm sorry if this isn't related to an issue. It's one question about serverless environment.
How to use this library on serverless with interface:
function handler = async (req, res) => {
...
}
?
replaceRoute = (name, params = {}, options) => {
const { page, pattern } = this.getRoute(name)
const { href, as } = createLinkProps(page, pattern, params)
return Router.replace(href, as, options)
}
prefetchRoute = (name, params = {}) => {
const { page, pattern } = this.getRoute(name)
const { href } = createLinkProps(page, pattern, params)
return Router.prefetch(href)
}
Should be NextRouter
router.add({
name: 'register',
pattern: '/register/:barcode?',
page: '/register',
})
doing
router.replaceRoute('register', {}, { shallow: true })
resulting in an address:
http://localhost:3000/register/
Is it intentional ?
Though it is working, I would like the address to not include the slash: http://localhost:3000/register
How to achieve this? Need change in the package source?
It would be nice to be able to use router events like in nextjs.
see:
https://github.com/zeit/next.js/#router-events
so in this repo something like this:
import Router from ../routes'
const handleRouteChange = url => {
console.log('App is changing to: ', url)
}
Router.events.on('routeChangeStart', handleRouteChange)
I know there's been a previous issue about query parameters: #2. However, that issue only talks about how to link to a page with query parameters.
The bigger issue is that adding query parameters to any URL (in the address bar of the browser, for example) causes no routes to match! All 404s.
This is because req.url
contains not only the pathname, but also the query string.
nextjs-dynamic-routes/src/Router.js
Line 63 in 3947447
The query string needs to be stripped out before trying to match routes. https://github.com/pillarjs/path-to-regexp#usage
Please note: The
RegExp
returned bypath-to-regexp
is intended for ordered data (e.g. pathnames, hostnames). It does not handle arbitrary data (e.g. query strings, URL fragments, JSON, etc).
Then, the query string needs to be parsed and be passed on to the page.
I monkey-patched the router in my routes.js
to fix the above problems:
const _ = require("lodash");
const Router = require("nextjs-dynamic-routes");
const router = new Router();
// Workaround missing query string support in nextjs-dynamic-routes. Query
// parameters caused routes not to match (404) and weren't passed on.
const { getMatchingRoute } = router;
router.getMatchingRoute = urlString => {
// https://stackoverflow.com/a/51525433/2010616
const url = new URL(urlString, "https://host/");
const urlParams = _.fromPairs(Array.from(url.searchParams));
// `.getMatchingRoute` is bound so it can be called directly.
const { page, params } = getMatchingRoute(url.pathname);
return { page, params: Object.assign({}, urlParams, params) };
};
router.add({ name: "home", pattern: "/" });
I haven't found a nice way to link with query parameters, but I still think that fixing the above issues alone is a good thing. I was very surprised when I started getting 404s. After triple-checking my route patterns I finally figured out it was because of a query parameter...
Like in this branch: https://github.com/gvergnaud/nextjs-dynamic-routes/tree/use-pathtoregexp
This way advanced URL patterns such as :foo+
and :digits(\d+)
can be supported.
https://github.com/pillarjs/path-to-regexp#compile-reverse-path-to-regexp
I want: the route to be named 'home' but file to be named 'index'
I write
router.add({
name: 'home',
pattern: '/',
page: 'index',
})
But the loading is stuck
If I change to:
router.add({
name: 'index',
pattern: '/',
})
It works.
Am I doing something wrong?
Last version of the lib, last stable next, react@next
"@emotion/core": "^10.0.6",
"@emotion/styled": "^10.0.6",
"@zeit/next-sass": "^1.0.1",
"express": "^4.16.4",
"formik": "^1.4.2",
"isomorphic-unfetch": "^3.0.0",
"js-cookie": "^2.2.0",
"next": "latest",
"next-compose-plugins": "^2.1.1",
"next-cookies": "^1.0.4",
"next-redux-wrapper": "^2.1.0",
"nextjs-dynamic-routes": "^2.3.0",
"node-sass": "^4.11.0",
"react": "^16.7.0-alpha.2",
"react-dom": "^16.7.0-alpha.2",
"react-easy-state": "^6.1.0",
"react-modal": "^3.8.1",
"react-progress-button": "^5.1.0",
"react-reim": "^1.14.1",
"reim": "^1.13.0",
"yup": "^0.26.6"
getMatchingRoute to return { name, page, pattern }
instead of { page, pattern } currently
Hi! I've faced this issue a couple of times,
.add({ name: "admin_index", pattern: "/admin", page: "/admin/index" })
That page doesn't work since it points to an index file.
Changing the file name to a different thing solves the issue
I used nextjs-dynamic-routes
in my router. all links is worked, but before refresh page , Shows me not found.
--pages
|
|- -index
| --blogs
| |
| |--index
| |--[post]
[post].js
class Post extends React.Component{
state={
data:null,
post:'',
title:'',
content:'',
imageUid:'',
status:0,
loading:true
}
componentDidMount(){
console.log(this.props);
this.setState({loading:true});
const post = Router.router.query.post;
if(post != undefined){
if(this.state.data == null){
this.getPost(post);
}
}
}
getPost = async (post)=>{
const res = await this.props.setPostDetalis(post);
this.setState({loading:false}),1000;
this.setState({
title: res.data.data.object.title,
content: res.data.data.object.content,
imageUid: res.data.data.object.attachments[0].uid,
data: res.data.data,
status:res.data.status
});
}
componentDidUpdate(){
const post = Router.router.query.post;
if(post != undefined){
if(this.state.data == null){
this.state.loading=true;
this.getPost(post);
}
}
}
Keywords = () => {
const data = this.state.data.tags.map((item) => item.title);
return data.toString();
}
render(){
return (
<div>
{this.state.title}
</div >
)
}
}
const pagePost = withRouter(Post);
const mapStateToProps = (state)=>{
return state
}
const mapDispatchToProps = {
setPostDetalis : setPostDetalis
}
const pagePostIndex = pagePost;
export default connect(mapStateToProps,mapDispatchToProps)(pagePostIndex);
router.js
const Router = require('nextjs-dynamic-routes')
const router = new Router()
router.add({ name: 'post', pattern: '/blogs/:post' })
module.exports = router
server.js
const express = require('express');
const next = require('next');
const { parse } = require('url');
const DEV = process.env.ENVIRONMENT !== 'production';
const PORT = 9000;
const app = next({dir: '.', dev: DEV});
const handle = app.getRequestHandler();
const getRoutes = require('./routes');
const routes = getRoutes();
app.prepare().then(() => {
const server = express();
//server.get('/blog/:id', (req, res) => ssrCache({ req, res }))
server.get('*', (req, res) => {
const parsedUrl = parse(req.url, true);
const { pathname, query } = parsedUrl;
const route = routes[pathname];
if (route) {
return app.render(req, res, route.page, route.query);
}
return handle(req, res);
});
server.listen(PORT, (err) => {
if (err) throw err;
console.log(`> READY FOR LIFOTFF http://localhost:${PORT}`);
});
});
Context: #15 (comment)
Currently, you can’t have query parameters with the same name as a URL param. The URL param takes precedence and the query param is discarded. For example, with the pattern /test/:id
, the URL /test/1?id=a
always gives you { id: "1" }
and you can’t see that the user passed id=a
.
In Next.js, if you pass the same query parameter multiple times, such as ?x=a&x=b
you get a query
object like this: { x: ["a", "b"] }
In other words, you get an array of all the values for the param.
Now to the question: Should we do something similar to support query params with the same name as URL params? For example, /test/1?id=a
could result in { id: ["1", "a"] }
. Or maybe the URL param should go at the end, since one might be used to take the last query param value when the user has given multiple but only one is supported? { id: ["a", "1"] }
.
So – why should we do this? It makes the library a little bit more flexible and "complete", I guess. But maybe it would just make things easier to screw up. It’s easy to forget that you might get an array and forget to handle that, or you might take the wrong value from the array. And I guess it’s easier to just rename the URL param or query param to not conflict, anyway. Probably makes your code easier to understand, too.
What do you think?
Hi. I don't know if i'm doing something wrong, but i have the following issue:
I have the route router.add({ name: 'index', pattern: '/(|index)', page: '/home' })
and this works for both url /
and /index
, which is what i want. But, when i have a Link that goes to the route index
, the url changes to /(%7Cindex)
, and i wanted to go to /
. My question is: there is a way to choose what pattern i would like to show on the url when i click on a Link?
I found a way to make it work by using two differents routes: router.add({ name: 'home', pattern: '/', page: '/home' })
and router.add({ name: 'index', pattern: '/index', page: '/home' })
, but i wanted to know if there was a way to make the same without duplicating the route.
I'm trying to use this with a path that has an optional path segment like this...
router.add({ name: 'company', pattern: '/company/:slug/:view?' })
The route works but generating routes with Link or Router doesn't quite work as expected. Currently, this is what happens...
Not including optional param:
Router.pushRoute('company', { slug='google' }
results in /company/google/:view?
Including optional param as an empty string:
Router.pushRoute('company', { slug='google', view='' } results in
/company/google/?`
Fortunately, the latter works well enough for me, but I would expect both to simply return /company/google
I'm not sure if you were intending support for this. It looks like the regex at the end of replaceWithParams is trying to do something like this, but doesn't quite match :view? as in my example above.
export const replaceWithParams = (pattern, params) =>
Object.keys(params)
.reduce((acc, param) => acc.replace(`:${param}`, params[param]), pattern)
.replace(/:[^\/&\?]*(\/|$)/g, '')
I wanted to find out if you have any interest in supporting this before submitting a PR. Also, before doing so I wanted to make sure I fully understand what that regex is supposed to do.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.