I have quite a lot of routes defined and one of the routes is dedicated to user profiles.
Each user has a public profile accessible from HTTP://example.com/#username.
I have tried creating file pages/#[username].js but it doesn't seem to work.
Is there a way to have this behavior without passing # sign with the username because this would greatly complicate index.js handling homepage and I would like to have that code separated.
You can now do this like so in next.config.js
module.exports = {
async rewrites() {
return [
{
source: '/#:username',
destination: '/users/:username'
}
]
}
}
This will make any link to /#username go to the /users/[username] file, even though the address bar will show /#username.
Then, in your /pages/[username].tsx file:
import { useRouter } from 'next/router'
export default function UserPage() {
const { query = {} } = useRouter()
return <div>User name is {query.username || 'missing'}</div>
}
Next.js does not support this yet.
You should watch this issue.
Related
I want to use the URL params and Queries into the vue router defining file in order to set the title name dynamically.
I tried to use the $route.params.paramName format:
const routes = [
{
path: '/rooms/:room/:id?',
name: `${$route.params.room}`,
component: RoomsView,
meta:{
title: `${$route.params.room} ${$route.params.id} - WebsiteName`
}
}
]
Do you know how can I access these values?
I think it's best to let the component itself render the logic with something like
computed: {
title() {
const { name, id } = this.$route.params;
return `${name} ${id} - WebsiteName`;
}
}
I think the docs would give you some useful insight as well
I have quite a lot of routes defined and one of the routes is dedicated to user profiles.
Each user has a public profile accessible from HTTP://example.com/#username.
I have tried creating file pages/#[username].js but it doesn't seem to work.
Is there a way to have this behavior without passing # sign with the username because this would greatly complicate index.js handling homepage and I would like to have that code separated.
You can now do this like so in next.config.js
module.exports = {
async rewrites() {
return [
{
source: '/#:username',
destination: '/users/:username'
}
]
}
}
This will make any link to /#username go to the /users/[username] file, even though the address bar will show /#username.
Then, in your /pages/[username].tsx file:
import { useRouter } from 'next/router'
export default function UserPage() {
const { query = {} } = useRouter()
return <div>User name is {query.username || 'missing'}</div>
}
Next.js does not support this yet.
You should watch this issue.
With the recent change regarding middleware https://nextjs.org/docs/messages/middleware-upgrade-guide.
Now the middleware also gets triggered by requests for /_next and /favicon.ico.
What is the best way to only trigger it for requests for /pages folder. There is the matcher but it would be cumbersome to type all of the pages in it.
I'm currently using middleware to check if cookies exist and redirect the user if the user accesses a page. E.g Redirect the user to /login if the user accesses / and the user is not logged in yet.
To avoid the middleware running when "/_next" or "/favicon.ico" routes are requested simply start your middleware function with:
const { pathname } = req.nextUrl
// Allow the requests if the following is true...
// 1) if the request is a system request /_next
// 2) if the request is to get the favicon.ico
if (pathname.startsWith('/_next') || pathname.startsWith('/favicon.ico')) {
return NextResponse.next()
}
Not sure it's the cleanest way but it works fine for me. Don't hesitate to tell me if I can make this better.
Now that middleware is stable (>=12.2), you can use a regex on the matcher to exclude some paths.
export const config = {
// matcher solution for public, api, assets and _next exclusion
matcher: "/((?!api|static|.*\\..*|_next).*)",
};
Ref: https://github.com/vercel/next.js/discussions/36308#discussioncomment-3758041
Here is the snippet of middleware:
// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
// This function can be marked `async` if using `await` inside
export function middleware(request: NextRequest) {
return NextResponse.redirect(new URL('/about-2', request.url))
}
// See "Matching Paths" below to learn more
export const config = {
matcher: '/about/:path*',
}
If you want middleware to run on all paths:
export const config = {
matcher: '/:path*',
}
Have you tried this.
I'm moving from a wordpress site to a new, shiny nextjs site. However, I have hundreds of redirects and I don't want to put them all in the nextjs config file. I like things clean and tidy. I searched around for awhile and didn't find any results on how to do this. Any suggestions?
You need to import it via require, tho remember that u also need to export it as module, so ex.:
const redirectsArray = [
{ source: "/about", destination: "/", permanent: true },
];
async function redirects() {
return redirectsArray;
}
module.exports = {
redirects,
};
and then
const { redirects } = require("./redirects.js");
I got it working while module exporting it as an array instead of an object in the redirects.js
module.exports = redirects
And then add it to the next.config.js like so
async redirects() {
return redirects
}
I am trying to implement alanning Meteor-roles with react-router in my Meteor application. Everything is working fine except the fact I can't manage properly to restrict a route using alanning roles or Meteor.user()
I tried with meteor-roles:
I am trying to use the onEnter={requireVerified} on my route. This is the code:
const requireVerified = (nextState, replace) => {
if (!Roles.userIsInRole(Meteor.userId(), ['verified'],'user_default')) {
replace({
pathname: '/account/verify',
state: { nextPathname: nextState.location.pathname },
});
}
};
I tried with Meteor.user():
const requireVerified = (nextState, replace) => {
if (!Meteor.user().isverified == true) {
replace({
pathname: '/account/verify',
state: { nextPathname: nextState.location.pathname },
});
}
};
So this is working when I am clicking on a route link, but when i manually refresh (F5), it does not work. After digging into it, i have found that Meteor.user() is not ready when i manually refresh the page.
I know Meteor.userid() or Meteor.logginIn() are working, but i wanted
to verify not just that they are logged but if they are "verified" or
have a role.
I also tried to check inside the component with react, with componentDidMount() or componentWillMount(), in both cases it's the same, the manual fresh does not load Meteor.user() before the compenent is mounted.
So what is the best way to restrict components/routes with meteor/alaning roles + react router ? (I am using react-komposer inside TheMeteorChef's base)
Thank you.
Note I have not tried it yet, it's only a suggestion
One thing you could try is to use componentWillReceiveProps alongside createContainer from 'react-meteor-data' like that:
import React, { Component, PropTypes } from 'react';
import { Meteor } from 'meteor/meteor';
import { createContainer } from 'meteor/react-meteor-data';
import { Roles } from 'meteor/alanning:roles';
class MyComponent extends Component {
componentWillReceiveProps(nextProps) {
const { user } = nextProps;
if (user && !Roles.userIsInRole(user._id, ['verified'], 'user_default')) {
browserHistory.push('/account/verify');
}
// If Meteor.user() is not ready, this will be skipped.
}
}
MyComponent.propTypes = {
user: PropTypes.object,
};
export default createContainer(() => {
const user = Meteor.user() || null;
return { user };
}, MyComponent);
To explain the flow, when the page is loaded, as you said Meteor.user() is not defined so you can't check the permissions. However, when Meteor.user() gets defined, this will trigger a refresh of the template, and the new props will be passed to componentWillReceiveProps. At this moment you can check if user has been defined and redirect if needed.
To be really sure not to miss anything, I would actually put the verification in the constructor() as well (defining a function that takes the props as arguments and calling it in both constructor() and componentWillReceiveProps()).