Router.push or Link not rendering/refreshing the page even thought the url is updated nextjs - javascript

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);
}
};

Related

Reflect changes without page refresh

I have created method to delete image as
action.js
export const removeImage = (id, image_id) => async () => {
try {
const response = await axios.delete(
`localhost:3000//api/v1/posts/${id}/delete/${image_id}`,
{
headers: {
'Content-Type': 'multipart/form-data',
},
},
)
I have call this method in post/[id].js as
<p onClick={() => removeImage(id, imgae.id)}>delete </p>
The problem is when I delete image I should hard refresh page to see changes. How can I solve this.
I have used useEffect hook
useEffect(()=> {
fetchData();
}, [data]);
It worked but load backend server too much.
Another idea I think to use useState hook. but how can I implement in this code?
Thanks in advance
I think that you try to do two different things :
Delete the image on your server with a request
Hide the image from your component / refresh your component src
You need to make the source image property of your component more reactive, like putting it in the state so you can modify it dynamically
Because here, you simply delete the resource on your server but your component is not refreshed or reloaded.
What you shoud do is to hide your component holding the image and display a kind of placeholder after clicking your delete button
Unless your app watches the server for updates you should manually reflect the changes you do on the server in your UI as well. For example, if you have a component, say an ImageButton, that is showing your image, and you remove the image from the server, what is the intended behavior? If you want the image button removed, you can simply set it’s visible property to false.

Vue: route navigation with router.resolve (to open a page in new tab) with data in params is lost

I have a component, lets call component 1. A method in component1 makes an axios.post request and the server returns a bunch of data. When data is loaded, a new button appears. When this button is clicked, it will be navigated to another route with another component, let call this component2. Now some of the loaded data from component1 needs to transferred to component2 and should be opened in new tab. Below is the code:
<script>
import axios from 'axios';
export default {
name: "CheckStandard",
data() {
return {
standard: '',
time: {},
programs: {},
example: {},
}
},
methods: {
checkData(){
let std= {
std: this.standard,
}
axios.post('http://localhost:3000/postdata', std)
.then(res => {
if (res.status === 200) {
if (res.data === 0) {
this.invalidID = "This Standard does not exist"
}
else {
let data = res.data
this.time = res.data["Starttime"];
this.programs = res.data["program"]
this.example = res.data["example"]
}
}).catch(error => {
console.log(error);
this.error = error.response
})
},
}
goToPictures(){
let route = this.$router.resolve({
name:'ProgramCheckList',
params: {
programs: this.programs,
time: this.time,
example: this.example
}
})
window.open(route.href,'_blank')
},
}
}
</script>
The function goToPictures is the function that is invoked after clicking the button. Now in this function goToPictures I have defined the route to navigate to another tab. But the problem the data in the params which it should carry is lost. I tried with $router.push ofcourse it works but it is not to open in new tab. Below is the code for the same:
goToPictures(){
this.$router.resolve({
name:'ProgramCheckList',
params: {
programs: this.programs,
time: this.time,
example: this.example
}
})
},
}
Since I am new to vue, I have tried my best to look for an answer for this, even I have came across some posts in several forums mentioning, it is may be not be possible even, instead advised to use vuex. But I still wanted to post it, maybe we have a solution now or any other idea. Thanks
The problem you're seeing stems from the fact that, when you open a new window, Vue is basically going to re-render your components as if you hit refresh. Your Component 2 has props that it can only inherit from another component, and as such, it has no possible way of knowing what the props it needs to use are.
To illustrate in simple terms what's happening:
The user navigates to Component 1. They click the button, which makes the GET request. You now have some data that you can pass onto Component 2 as props.
In a regular environment, the user would simply click on the link leading to Component 2, and the props would be passed on normally, and everything would work as intended.
The problem in your situation is that Component 2 depends on Component 1 for its data. By navigating directly to the Component 2 route (in this situation, opening a new window is functionally identical to a user copy/pasting the url into the adress bar), Vue never has the chance of interacting with Component 1, and never gets told where to get the props it needs to populate Component 2.
Overcoming the issue
There's a few things you can do here to overcome this issue. The most obvious one is to simply open Component 2 as you would normally, without opening a new window, but keep in mind that even if you do this, should a user copy/paste the URL where Component 2 is, they'll run into the exact same issue.
To properly deal with the issue, you have to specify a way for Component 2 to grab the data it needs. Since the data is already fetched, it makes sense to do this in the created() or mounted() hooks, though if you wanted to you could also deal with this in Vue Router's beforeRouteEnter() hook.
Vuex
While you don't necessarily need a state management tool like Vuex, it's probably the simplest way for your needs. When you grab the data from Component 1, store it and access it from the Component 2 mounted() hook. Easy-peasy.
localStorage()
Alternatively, depending on how the data is being served, you could use localStorage(). Since you're opening a new window, sessionStorage() won't work. Do note that localStorage() can only hold strings and nothing else, and isn't necessarily available in every browser.
You can store the data to a global variable and use that in the newly opened window. Asked here Can I pass a JavaScript variable to another browser window?
Provided the windows are from the same security domain, and you have a reference to the other window, yes.
Javascript's open() method returns a reference to the window created (or existing window if it reuses an existing one). Each window created in such a way gets a property applied to it "window.opener" pointing to the window which created it.
Either can then use the DOM (security depending) to access properties of the other one, or its documents,frames etc.
Another example from same thread:
var thisIsAnObject = {foo:'bar'};
var w = window.open("http://example.com");
w.myVariable = thisIsAnObject;
//or this from the new window
var myVariable = window.opener.thisIsAnObject;

Mithril component not updating when route changes

I am creating my personal website/blog as a a single page application using Mithril.js. All pages and blog posts on my website are rendered using Page and Post components, and the correct page is loaded based on the :slug in the URL.
The problem I have is that whenever I try and switch between pages, the content of the page does not update. Switching between pages and posts works because I am alternating between Page and Post components. But when I try and use the same component twice in a row, going from page to page, it doesn't update the webpage.
m.route(document.body, '/', {
// `Home` is a wrapper around `Page`
// so I can route to `/` instead of `/home`
'/': Home,
'/:slug': Page,
'/blog/:slug': Post
});
const Home = {
view() {
return m(Page, { slug: 'home' });
}
};
Here is the Page component (the Post component is very similar). Both components render correctly.
const Page = {
content: {},
oninit(vnode) {
m.request({
method: 'GET',
url: 'content.json',
}).then((response) => {
Page.content = response.pages[vnode.attrs.slug];
});
},
view() {
if (Page.content) {
return [
m('#content', m.trust(Page.content.body))
];
}
}
};
Why isn't Mithril recognizing that the slug changed?
The docs page for m.route has a solution for you.
When a user navigates from a parameterized route to the same route with a different parameter (e.g. going from /page/1 to /page/2 given a route /page/:id, the component would not be recreated from scratch since both routes resolve to the same component, and thus result in a virtual dom in-place diff. This has the side-effect of triggering the onupdate hook, rather than oninit/oncreate. However, it's relatively common for a developer to want to synchronize the recreation of the component to the route change event.

How to find Popup state and refresh state in React-router?

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.

React page does not rerender on url query change

I'm trying to create a react page having different content based on the query in the url. ex: things?type=0 and things?type=1 resulting in different filtered content.
The problem is, React isn't triggering a rerender of my page when switching to these pages. I need to manually refresh the page to get the desired result.
I tried to use the build in lifecycle features but non of them triggers the page to refresh. It tried to do my fetch in the componentWillReceiveProps method with then I have to click twice on the link to get my filtered content (which is better than no page refresh but not user friendly).
I use this reference.
You will probably want to use https://github.com/reactjs/react-router or some similar library for routes.
If you want to go on your own you have to listen to browser history changes. You could do it like this for example:
componentDidMount: function () {
var component = this;
window.onpopstate = function() {
console.log(window.history.state);
component.setState({
query: window.location.search
});
};
};
I am not sure if this is the good way to go, but it should work at least.

Categories