NextJS route shows [slug] in url - reactjs

I have a NextJS app with the folder structure:
- pages
- docs
- [slug]
- index
- [id]
- index
These pages are supposed to be dynamic based on the data that appear in the UI. Meaning a user can go to /docs/payments/introduction (where payments and introduction are dynamic pages too).
However everything works fine when the user is one level deep in the nesting eg (docs/payments), but when the user goes 2 level deep (eg docs/payments/introduction), all the links begin showing [slug] in their url. Let's say there's a link in the sidebar that's supposed to go to /docs/payments/faq it then starts showing /docs/[slug]/faq in the url.
Here's a screenshot of an example url
I have no idea how its happening.

You need to use [...slug].tsx to be able to use multiple slugs.
- pages
- docs
- [...slug].tsx
If you want more info, click here.

Are you sure you are using Links and router.pushes correctly? When using dynamic slugs, you should use as prop. Like this:
<Link as="/page/docs/getting-started/creating-an-account" to="/page/docs/[slug]/[id]">
<a>Link</a>
</Link>
or if you are using router, like this:
const router = useRouter();
router.push('/page/docs/[slug]/[id]', '/page/docs/getting-started/creating-an-account');

Related

How to view the list of history paths in react-router?

Is it possible to view the list of paths in the history object? I can see that there is the length but I need to see the actual paths.
The reason for this is for debugging purpose. I have 2 views (SPA) that gets displayed via their corresponding URL. But my problem is when I go from the first page to the next page and then I wanted to go back to the first page, I need to click the browser back button 2 times before it goes back to the first page. That's the reason I wanted to see what are the paths in the history object so I can check what entries are being added because as far as I can see, the code I have to add a path to the history object is straightforward:
props.history.push("/classes/" + courseId);
That's just the code so I don't know why I need 2 clicks to go back to the previous page.
Not exactly sure how to see the history stack, but you might be unintentionally rendering the page twice, so the history.push is working as intended. You can log in componentDidMount to see if it does, and be careful when using useEffect because that can cause that as well. If you're using react router check how the route is added in your app.js (for ex do <Route path="/classes/:courseId" component={courseId}> instead of <Route path="/classes/:courseId" render={()=>courseId()}>.

ReachRouter navigate in component constructor

If a user goes to a page that requires a context beyond what's on the url, I'd like to redirect them elsewhere. The use case is:
/todos/list - this page shows the user their list of todos. It contains links to:
/todos/edit?id=1 - this page allows the user to view/edit details about a particular todo.
If a user were to go directly to /todos/edit (with no id), I'd like to redirect them to /todos/list. I have tried doing this via navigate('list') conditionally in the constructor. This does update the browser url correctly, but it doesn't render the /todos/list page. Is this possible to do? Or is this not possible to do the para below?
I understand the more common url would be /todos/edit/1 so that reach router would handle my issue w/out me needing to deal with it. However, I'm just using this as an example of a piece of information required to render the page that isn't necessarily part of the the url path.
of course as soon as I type the question in stackoverflow, I find the answer is in the docs right in front of my face:
https://reach.tech/router/api/Redirect

reactjs routing to a specific section of a different page

from page 1 I am trying to route to a specific section of page 2.
I tried to use the hash value in the Link component but it did not work
<Link to={ {pathname: `/page2`, hash: `#sectionID`}} >
I even used this package react-router-hash-link with no success.
I always end up at the top of page 2.
any help
Check This link for full explanation;
Hash link scroll functionality for React Router, and here is example that will scroll to the component when you open it: baz#section-three, another one baz#section-two

2 levels nested routing in nextjs

I carefully read the docs of next routing system.
It only mentions that I could achieve dynamic routing like this:
http://localhost:3000/level1/dynamicSlug
But I am trying to achive something like this:
http://localhost:3000/level1/level2/dynamicSlug
And I want level2 to be created dynamic too
Thanks so much !
It is possible to do nested scenarios according to your request in this way.
for example:
pages/
level1/
[dynamicSlug]/
- index.js // will match for /level1/1234
level2/
- index.js // will match for /level1/level2
- [dynamicSlug].js // will match for /level1/level2/1234
Or
pages/
level1/
[dynamicSlug]/
- index.js // will match for /level1/1234
level2/
- index.js // will match for /level1/level2
[dynamicSlug]/
- index.js // will match for /level1/level2/1234
You have 2 choices:
Using v9 Dynamic Routing by calling the folder as [dynSlag] and putting your page file inside.
Using custom server and routing, you will need to define a custom server, map your path to a specific next page.
I know this is a bit of an old post, but I'd just like to share my working response with NextJS v11.
I want dynamic routing at two levels. E.g.:
{siteroot}/dynamicPage
{siteroot}/dynamicUrlSection/dynamicPage
My folder structure is:
/pages/[section]/[page].tsx
/pages/[section]/index.tsx
This way, the "dynamicPage" path at the root is handled by index.tsx, and nested routes are handled by [page].tsx
BONUS INFO: I am working with Contentful as a CMS. I use a single content model for all the pages at both levels.
The model has "section" and "page" properties.
The entries that serve the root dynamic pages (i.e. /pages/[section]/index) have a compound value in the "page" property of {section}-index. I then have to be a bit smart in my client code:
if (!page) {
page = `${section}-index`;
}
await fetchData(section, page);
Using the example right from the NextJs documentation, I use this hack, maybe you could use it.
<Link href="/posts/[id]" as={`/posts/${subFolder}${id}`}>
"as" will have a value like /posts/nested_subfolder_file.md
And in the getPostData function, just do this little change:
const nestedPaths = id.split('_')
const fileName = `${nestedPaths.pop()}.md`
const fullPath = path.join(postsDirectory, ...nestedPaths, fileName)

React Router setup for 'unlimited' params

I am trying to implement the React Router in such a way that it supports a route like this:
/myPages/:pageName1/:pageName2/:pageName3/...
The idea is that, even though the page being rendered is only the last page, the pages are nested, and the depth is not something that is pre-determined. The component that renders the actual page needs to know the names of parent pages.
To clarify, the idea is that the page data in the backend are in a tree structure in such a way that, in the above example, page1 is the root page, page 2 is a child of page1, page 3 is a child of page2, etc. In addition, one page can have multiple children. The last child name (so pageName3 in the example) is what is being used to query the database and get all the content required to render the full page. The parent names are required to render navigation-related subcomponent. I should also mention that just having /myPages/:pageName3 and getting all parent names from the backend is not really an option. I could fetch that information from the backend, but the URL presented to the user still needs to have that structure.
I am hoping that there's a way to get this type of information as an array, but I am having a hard time finding an example like this on the web.
maybe this can help.
https://github.com/ReactTraining/react-router/blob/d28d46dce08a5756a085f7e5eebb5169ea59e40b/packages/react-router/docs/api/Redirect.md#from-string
states:
A pathname to redirect from. Any valid URL path that path-to-regexp#^1.7.0 understands.
maybe you can combine
<Redirect from='/users/:id' to='/users/profile/:id'/>
with
var re = pathToRegexp('/:foo+', keys)
(taken from https://github.com/pillarjs/path-to-regexp/tree/v1.7.0#one-or-more)
then you'll end up with
<Redirect from='/:pageName+/:id' to='/:id'/>

Resources