I am trying to redirect with react router to another page after a certain amount of time has passed.
The code I have so far is:
submitActivity(){
axios.post('/tiles', {
activityDate:this.state.startDate,
planId:this.state.planId,
value:this.state.sliderValue
})
.then(res=>{
console.log(res);
this.modalHandleShow();
setTimeout(function(){
this.goBackToTile();
}.bind(this),3000);
})
.catch(err=>console.log(err));
}
goBackToTile(){
this.props.history.push(`tile/${this.state.tileId}`)
}
history is definitely being called, but the url which is currently
/addActivity/tile/2/plan/9
only gets changed to
/addActivity/tile/2/plan/tile/2
while /tile/2 is correct I don't understand why the rest of the url stays in tact?
Make sure you include a / in the beginning of the string, or it will be used relative to your current url.
goBackToTile() {
this.props.history.push(`/tile/${this.state.tileId}`)
}
Related
I apologize for my horrendous way of explaining my issue. I have shared a link below description which is exactly the same issue I am experiencing. Any kind of help would be greatly appreciated.
I have directory path like pages/request/[reqid].js . When my url is localhost:3000/xyz and I navigate to pages/request/1 by clicking a button on the current page, the page successfully loads the page with proper data from [reqid=1] but when I try to access pages/request/[reqid].js with different reqid (say suppose reqid=2), the url reflects the correct the reqid pages/request/2 but the page remains the same, doesn't change. However if I go back to other pages like localhost:3000/xyz and click a button there to navigate to pages/request/2 it works but from within pages/request/[reqid] it doesn't render a page associated to the corresponding reqid even thought the url is updated. I have tried both Link and router.push ,both fails to render the correct reqid page.
https://github.com/vercel/next.js/issues/26270
It actually failed to include that I was using getServerProps to fetch the data, which was the reason the page wasn't rendering , unless the page was manually refreshed. The page state is not reset for navigation between dynamic routes that served by the same source component.
for example, give page source /a/[param]/index.js, when navigating from /test/123 to /test/124, states on the page wasn't being reset.
So actually happened is the same React Component been rendered with different props. Thus react takes it as a component is rerendering itself, and causing the new navigated page receive stale states.
To fix it, just add {key: } to page initial props or getserversideprops
export const getServerSideProps = async (ctx) => {
try {
const { reqid } = ctx.params;
//fetch code
return {
props: {
key: reqid,
data:data
},
};
} catch (error) {
console.log(error);
}
};
This question already has answers here:
How to get previous url in react gatsby
(4 answers)
Closed 2 years ago.
Is there any way to find the path of the page that a user is on on a Gatsby site and store it in a const so that it can be checked next to the current path the user is on? In other words if they're on the /about page, and are clicking a link to navigate to the /contact page, I need to get the paths of both so that I can check them against each other. I know I can get location.pathname for the current url, but how do I find the path that they are navigating to when the click a link?
Since your code structure isn't clear. Assuming a simple anchor tag, you can do something like this:-
<a href="/new/link" onClick={getHref}>New Link</a>
And in your getHref method
function getHref(event){
console.log(event.target.href); // should log '/new/link'
}
Check if this works in your case.
Please forgive for any typo, I havent validated it.
Gatsby exposes props (because it extends from #reach/router from React) by default on the top-level components (this means pages). You can pass it to the child components as you wish or store it in a const or in a React's state.
Without knowing any page structure, I'll provide something dummy as an example:
import React from "react"
import { graphql } from "gatsby"
const YourPage = ({ location, data }) => {
console.log('your page is ', location.pathname)
return <div>Dummy content</div>
}
export default Page
export const query = graphql`
query PageQuery {
site {
siteMetadata {
siteURL
}
}
}
`
Your information is stored under props.location, that's why you can destructure it in the component's declaration.
In the case above, I've used pathname property but you have a bunch exposed. Check it out to find out which one fits your requirements.
I have a website as a single page that is using Next.js. I have the home page on route / that show a list of products. The code of this page is located in pages/index.js. Each product has an id so I can jump to it using /#product-id.
To make it more url friendly I replicate this behaviour using the product-id as a second param in the route like that: /product-id.
What I do is simply looking on the product-id param using useRouter():
const selectedProductId = useRouter().query['product-id']
And then scroll to the element with this id using js:
document.getElementById(selectedProductId ).scrollIntoView()
So I to change my script name from /pages/index.js to /pages/[product-id].js.
So now the route /1234 work has expected but if I go to / I get error 404.
So has someone an idea how I can match / and /param using one js file?
Optional catch all routes
Catch all routes can be made optional by including the parameter in double brackets ([[...slug]]).
Nextjs has file system based routing, so if you remove /pages/index.js of course you will get an 404 error. Also /pages/index.js and /pages/[product-id].js will render two separate pages.
To answer your question, if it is possible to match two routes like / and /[productId] in one file using nextjs I don't think that is possible however similar results can be achieved by using shallow routing specific to your use case.
So for your use case, I suggest using shallow routing unless you want to render the same component in both pages just to get the product-id or want to make use of hash URLs.
You can make product-id a query string parameter and update it using shallow-routing. Here is an example,
Keep /pages/index.js
import { useRouter } from 'next/router';
const router = useRouter()
// when want to change the productId call
router.push('/?productId=1234', undefined, { shallow: true })
// call the scrollToView inside a useEffect hook
useEffect(() => {
const productId = router.query.productId
// get the element using the productId above then call scrollIntoView()
})
// if using useEffect with the dependency router.query.productId,
// when you change the productId once and scroll up and try to change to the same -
// productId again it will not scroll to view, hence not using the dependency array
// at all
To explain more on what shallow routing does
Shallow routing will allow the change of URL without running the data fetching methods i.e getStaticProps or getServerSideProps again. Which will make the updated query and pathname available without changing the state. Read more about it nextjs docs.
Option 1: Extract the shared code
You could extract a Page component to a separate file and then import it in both /pages/index.js and /pages/[product-id].js, so the code is not duplicated.
Option 2: Use experimental rewrites feature
Assuming you have /pages/[product-id].js you can show this page when a user requests /.
You would need to add next.config.js.
module.exports = {
experimental: {
async rewrites() {
return [
{ source: "/", destination: "/[product-id]" },
];
}
}
}
So, when a user requests / they would see the content of /[product-id], just with the empty product id.
Note, that at the moment rewrite doesn't support auto-rendered dynamic pages, so you have to disable auto-rendering for the dynamic page.
You can do that by adding getServerSideProps to /pages/[product-id].js.
export async function getServerSideProps() {
return {
props: {},
}
}
I need to change url completely using following way.
let mycomplteUrl = 'http://localhost/tracks/id/4/39'; // http://localhost/tracks/id/4/39/4 or
props.history.push(`${mycomplteUrl}`);
I'm dynamically creating this mycomplteUrl variable. sometimes variable can be something like
http://localhost/tracks/id/4/39 or http://localhost/tracks/id/4/39/4 or http://localhost/tracks/id/4/39/4/5 (dynamic) or any
it is the same only up to http://localhost/tracks/id/4 this part. I need to replace whole url just like window.location.href = mycomplteUrl in normal javascript, but using props.history.push because i need to avoid from page refresh
Note: for React Router v6
import { useNavigate } from 'react-router-dom';
function MyComponentOrHook() {
const navigate = useNavigate();
// push
navigate(url); // syntax
navigate("/about"); // example
// replace
navigate(url, { replace: true }); // syntax
navigate("/about", { replace: true }); // example
return ... // JSX or hook return values
}
Also, avoid using window.location if you're using React Router, except in rare cases (example - to navigate to an external link).
Reason:
The whole point of using a library React Router is to ease client-side routing so we don't have to do window.location....
window.location causes a reload, which should be avoided in React apps (or any SPA), mostly.
props.history.replace(mycomplteUrl);
If you want to avoid from a page refresh you can do it in this way
window.history.pushState({}, null, "/newPathname");
Try the below way and define the exact URL you want.
window.location.replace(`http://localhost:3000/${dynamic_value}`);
I know this question kind a stupid But I am pretty confused with this site producthunt how they are doing this.When clicking the product list popup with react router is done like this..
But When I refresh that page it render like this..How this is done using React-router
My bet would be that they use the state property when pushing a page to give an indication to the component about how to render the page. More specifically, to indicate the component where it comes from. For example:
router.push({
pathname: '/posts/origami-studio-by-facebook',
state: { fromPosts: true }
})
And then you can read the router's state in the route's component to check what page to show.
const Post = (productName) => {
if(this.context.router.location.state.fromPosts) {
return <Posts productPopup{productName} />
// open the posts page with a popup for the product
} else {
return <PostPage productName={productName} />
}
}
So when you open the page in your browser, the state.fromPosts is not set and you get redirected to the PostPage. In the end, even if the route is the same, what you end up seing is completely different.