I want to have user profiles in my app at domain.com/:username .How do I do it? creating a new folder in /pages will create a new URL section like /user/:username which I don't want.
Just name your file inside pages as [username].js
Creating a dynamic route
You can create a dynamic route by putting the filename in brackets. For instance:
pages/[id].js
pages/[slug].js
pages/posts/[slug].js
pages/[author]/[slug].js
pages/[author]/bio.js
Notice how the dynamic route can be at any level. It doesn't simply need to be at the root of the pages folder, and it doesn't need to be the last level of the url either. Also notice that you can name the dynamic route anything you want. You're not restricted to just using [id] or [slug].
In your case, use pages/[username].js
Accessing the route name
If you create a dynamic route at pages/posts/[slug].js, any page at https://example.com/posts/slug-of-the-post will lead to that page. However, you likely want different content on each page (i.e., that the user is on https://example.com/posts/slug-of-the-post, not https://example.com/posts/slug-of-a-different-post. For this, you need to access the contents of the route.
Inside the page
You can use the router to get the name of the route.
// pages/posts/[slug].js
import { router } from 'next/router'
export default function PostPage() {
const router = useRouter()
const slug = router.query.slug // "slug" because that was the name of the file
return <>{/* page contents */} </>
}
So on page https://example.com/posts/slug-of-the-post, the variable slug will be slug-of-the-post.
If you used [id].js, use router.query.id instead.
GetStaticProps/GetServerSideProps
Using the server-side functions, the process is very similar.
// pages/posts/[slug].js
// bottom of the file
export async function getServerSideProps(context) {
const slug = context.params.slug
return {
props: {},
}
}
Docs
By the way, I'd also recommend checking out the docs if you haven't already:
https://nextjs.org/docs/routing/dynamic-routes
Related
I am developing a nextjs project and I have a page that has dynamic routing, something like this :
.../user/[id]/[another id]
I want to set a unique route for every user. but assuming the nextjs default routing system, it seems I have to create a single page for every user.
I wonder if there is any way to set a specific route like '/john' for every user that represent the same page for the route: .../user/[id]/[another id]
can anyone help me with this?
thanks.
You can just create a page in the /pages or /src/pages directory like this:
[user].js
then you can read this value in your component as :
const UserComponent = ({user})=>{
return <p>{user}</p>
}
UserComponent.getInitialProps = (ctx) => {
return { user: ctx.query.user }
}
export default UserComponent;
Here I'm trying to pass the variable header_url data to my other vue pages. Since I also want to use this for push and post methods in the other vue script tags. I'm not sure how to do it? Since, I can only find examples with data been transferred between html tags.
// Home.vue
<template>
<div>
Home
<h2>logout</h2>
<a v-bind:href="url">logout</a>
</div>
</template>
<script>
export default {
data: () => ({
url:"https:..."
})
}
var header_url = window.location.href;
if (header_url.length>100) {
var token=window.location.href.match(/\#(?:id_token)\=([\S\s]*?)\&/)[1]; // eslint-disable-line
console.log(token);
}
</script>
To pass data between two URLs in single page app, you need use Vue Router
and Route Meta Fields.
From the docs :
Sometimes, you might want to attach arbitrary information to routes like transition names, who can access the route, etc. This can be achieved through the meta property which accepts an object of properties and can be accessed on the route location and navigation guards
In my vue application I have a component page that contains five components. I also use vue composition api.
each component is lazy, it resolve when the component is in the viewport. because of that I need to write the logic only inside the component. (not in the parent).
so far so good, but two of components inside product.vue depend of the route params value. say /product/2.
the product.vue looks like that:
<intro> -> just a raw text (no need to fetch from the server, not need to wait to load)
<foo> -> need data from the server base on the productId from the route.params.
<txt> -> just a raw text not need to get the data from the server
<bar> -> need data from the server base on the productId from the route.params.
Important notes:
In case I don't need data from the server like intro I want to render it immediately. so for all similar components in this page.
for example intro render right way, the foo will render when it enter to the viewport and display a loader and when the data is resolved it change to the data.
I want to see the page ASAP. so each component have its own loader.
Here I become with some problems:
One: I need to know if the product exist. if not it need to be redirect to 404 page. so where to put this logic? each component or the parent component? I think the parent component, but when it take 2 min to load the data I'll get a blank screen seince the components are not ready and not be render. which is conflict with "Important notes".
Two: when the productId is change (navigate to another product) the foo and bar need to resolve the data, so in those two components I need to listen to the route change (which makes duplication in my code) (and slow performance?) and still I need to check if the productId is exist or not.
in this example the items don't change because it need to trigger the useProduct function.
setup() {
const { route, router } = useRouter();
const productIdToLoad = computed(() => route.value.params.productId);
const { items } = useProduct({ productId: productIdToLoad });
return { items }
}
and if I do it in watch I lose the reference
setup() {
const { route, router } = useRouter();
const items = ref([]);
const productIdToLoad = computed(() => route.value.params.productId);
watch(productIdToLoad, (v) => {
items = useProduct({ productId: v });
});
return { items }
}
I am creating a VueJS app in which the user fills out a 5-step form.
These steps are routed to /step-1 through /step-5 in the Vue Router. However, I would like the site to return to the index page (/) when refreshing the page.
I could use abstract mode for this – but the result page is generated from the following url: /result/:userid in which I need the state to be history in order to be able to get the userid from the URL (and then do a post request to the server).
I also want this URL to be accessible even after finishing the form, so abstract here is not an option unfortunately.
So – is it possible to use both modes? Refresh the page to index.html when refreshing the form-pages, but then use history mode to render the result?
You cannot do this. It is either history or abstract but not both. Having said this, there are a couple of things you can do.
Approach 1: Use history mode with steps as query params
So instead of having routes like /step-1 or /step-2, use then as part of query params. So you will have routes like:
Index route: example.com/?step=1, example.com/?step=2
Result route: example.com/result/:userId
Approach 2: Use abstract mode with higher order component
Here, you will have a router with abstract but it will only serve as a state router and won't help with any browser URL manipulation.
Build a higher order component like AppComponent where you will have your own regular expressions to determine the route. It would look like:
// Should match route /result/:userId
const IS_RESULT = new RegExp('/result/(\\d+)$');
// User RegExp groups
const IS_STEP = new RegExp('/step-(\\d+)$');
export default class AppComponent extends Vue {
// Use Vue.js created hook
created() {
const path = window.location.pathname;
// Top level routing of the application
if (IS_STEP.test(path)) {
// Do something. You are in step-1/step-2/etc.
} if (IS_RESULT.test(path)) {
// Do something. You are in /result/:userId
// Get userId
const groups = IS_RESULT.exec(path);
const userId = groups[1];
} else {
// Goto Error page
throw new Error('Unknown route');
}
}
}
Approach 3: Use Multi-page SPA
Here, you will create two single page application. The first app will have routes /step-1, /step-2, etc. You will use abstract mode for this. The second application will have /result/:userId route with history mode.
In this architecture, when a user is on step-5, instead of pushing a new state to the router, you will use HTML5 history API to change the router and then cause a forced page refresh. Also, there are other ways you achieve this.
You can simply have a redirect in native javascript where you call it window.location.href('yourHomePage.com') and it will do a full refresh.
when u seem to require forward in reactjs we used to put a Link or button ,and then consumer click it ,then the page reload corresponding path of router . Now,I want the page turn to other path of router when I request a post and the status of response is 200. It can't use a link or button ,could reactjs use code to do this? like : CertainComponent.setPath(otherPath); CertainComponent.turn;
My English is poor , it may be not clear to delive the function which i want to do.
Thanks!
I think you want to use this.context.router.push('/users/12')
https://github.com/reactjs/react-router/blob/master/docs/API.md#routercontext
First of all the component you are using has to be a container, which means you have to create it with connect() so it has access on store and dispatch:
let MyComponent = ({ dispatch, store }) => {
store.routing.push('url');
}
export default connect()(MyComponent)
And this depends how you named the router key on your store when you combined the routing reducer from redux-router on your store.
There is also another alternative, where you could do
import { hashHistory } from 'react-router';
hashHistory.push('next-url');