Nuxt3: Refresh useFetch data on page navigation - nuxtjs3

I have a comment component that fetches data using useFetch and user can sort the comments by time, likes, etc. Works good, However, the problem is that when user navigates to another post page with this comment component, the comments are not refreshed and thus the old commments from the previous blog page is still shown.
How do I refresh the data on new pages?
Here's my code:
const selectedSort = ref('newest')
const { data, pending, error, refresh } = useFetch(
`/api/comments/${selectedSort.value}/${route.params.id}`
)
I tried to add:
watch(
() => route.params.id,
async (newId) => {
refresh()
)
but that did not work...

Related

How to e.preventDefault() when clicking on Update in Gutenberg, WordPress

How to e.preventDefault() when clicking on Update in Gutenberg, WordPress?
What I'm trying to do is check something and if there is any error, I will prevent the update process and show the error.
My code:
$(document).on('click', '#editor .editor-post-publish-button', function (e) {
e.preventDefault();
// Show Errors...
});
However, the e.preventDefault() is not preventing the process and the post is getting updated.
With JavaScript, you can use the core WordPress Block API to issue error notices if your own validation logic detects any issues and prevent the post from saving if errors are present, eg:
JavaScript
// Create error notice
wp.data.dispatch('core/notices').createErrorNotice(
'A value is required', // Message displayed to User
{
id: 'my-field', // Used to remove notice and check if notice is present
isDismissible: false,
}
);
// Remove notice
wp.data.dispatch('core/notices').removeNotice('my-field'); // unique id 'my-field'
// Prevent post from saving
wp.data.dispatch( 'core/editor' ).lockPostSaving( 'my-field' );
// Enable post saving
wp.data.dispatch( 'core/editor' ).unlockPostSaving( 'my-field' );
By using native WordPress API, displaying and styling of the notices is taken care of and keeps the UX consistent. The Documentation also has an example of preventing a post from publishing which may be helpful as well.

404 Page Being Shown While NextJS Page Is Rendering

I build all of my initial routes for a dynamic slug based on what I have available in my CMS at build time. Then as new CMS data is available, I will generate new pages when they are requested by the user.
I'm running into an issue where a user might hit /posts/1, but since posts/1 has no CMS data, I'm rendering the 404 page using the notFound boolean inside of getStaticProps. This is what I expect to happen.
Now, if I publish some data to /posts/1 in my CMS, the next time a user hits /posts/1, the API data is fetched in the getStaticProps method, and the page begins to build. The problem is that the user is immediately redirected to the 404 page even though the notFound block is not hit. The router.isFallback flag is also shown as false when it should be true since the page is building. Now, if this user were to refresh their page, they would see the generated page and no longer the 404 page since it is now built.
It seems like Next might route the user's request to the 404 page in the second scenario since it was previously a 404, but is there some way I can "block" the user's request or show my fallback until the page is rendered so that they don't see this 404 when the page is building? This scenario would not happen if the first user did not hit this slug before there was CMS data available.
Here's a simplified example of how I am using getStaticPaths and getStaticProps:
export const getStaticPaths = async (ctx) => {
const myInitialPaths = await fetch('http://my-cms-endpoint.com/initial-paths/');
return {
paths: [
...myInitialPaths
],
fallback: true
}
}
export const getStaticProps = async ({ params }) => {
const myPageData = await fetch('http://my-cms-endpoint.com/page/#id');
if (myPageData) {
return {
props: {
myPageData
}
}
} else {
return {
notFound: true
}
}
}

How to keep waiting Vue until getting data from firebase?

I have a project that showing posts from a firebase realtime database. I use Vue, Vue-Router and Firebase Authentication. Firstly, when a user open the website, user see a login screen. In that screen page loads the posts from my database. Then when user login he/she routing to my Home.vue page. In here posts are showing there is no problem. But when user refresh the page, elements that are in the Home.vue are loading faster than my firebase data. I want to fix it.
That is my function that loads late from another javascript file:
function getData(data) {
var posts = data.val();
var keys = Object.keys(posts);
for(var i = 0; i < keys.length; i++) {
var id = keys[i];
var user = posts[id].user;
var text = posts[id].text;
var date = posts[id].date;
userPosts.push({
id: id,
user: user,
text: text,
date: date
});
}
userPosts.reverse();
}
export var userPosts = [ ];
You gotta look for lifecycle hooks in vue.js and use the one hook that triggers before/when the page is (re)loaded.. In it you set a Promise with your firebase function, that triggers getData() when resolved and go through with the chosen lifecycle hook.

Vue JS AJAX computed property

Ok, I believe I am VERY close to having my first working Vue JS application but I keep hitting little snag after little snag. I hope this is the last little snag.
I am using vue-async-computed and axios to fetch a customer object from my API.
I am then passing that property to a child component and rendering to screen like: {{customer.fName}}.
As far as I can see, the ajax call is being made and the response coming back is expected, the problem is there is nothing on the page, the customer object doesnt seem to update after the ajax call maybe.
Here is the profile page .vue file I'm working on
http://pastebin.com/DJH9pAtU
The component has a computed property called "customer" and as I said, I can see in the network tab, that request is being made and there are no errors. The response is being sent to the child component here:
<app-customerInfo :customer="customer"></app-customerInfo>
within that component I am rendering the data to the page:
{{customer.fName}}
But, the page shows no results. Is there a way to verify the value of the property "customer" in inspector? is there something obvious I am missing?
I've been using Vue for about a year and a half, and I realize the struggle that is dealing with async data loading and that good stuff. Here's how I would set up your component:
<script>
export default {
components: {
// your components were fine
},
data: () => ({ customer: {} }),
async mounted() {
const { data } = await this.axios.get(`/api/customer/get/${this.$route.params.id}`);
this.customer = data;
}
}
</script>
so what I did was initialize customer in the data function for your component, then when the component gets mounted, send an axios call to the server. When that call returns, set this.customer to the data. And like I said in my comment above, definitely check out Vue's devtools, they make tracking down variables and events super easy!
I believed your error is with naming. The vue-async-computed plugin needs a new property of the Vue object.
computed: {
customer: async function() {
this.axios.get('/api/customer/get/' + this.$route.params.id).then(function(response){
return(response.data);
});
}
}
should be:
asyncComputed: {
async customer() {
const res = await this.axios.get(`/api/customer/get/${this.$route.params.id}`);
return res.data;
}
}

Structuring a reducer for a simple CRUD application in redux

So I'm creating what is at it's core a very simple CRUD-style application, using React + Redux. There is a collection of (lets call them) posts, with an API, and I want to be able to list those and then when the user clicks on one, go into a detail page about that post.
So I have a posts reducer. Originally I started using the approach taken from the redux real-world example. This maintains a cache of objects via an index reducer, and when you do a "get post" it checks the cache and if it's there, it returns that, else it makes the appropriate API call. When components mount they try to get things from this cache, and if they're not there they wait (return false) until they are.
Whilst this worked OK, for various reasons I now need to make this non-caching i.e. everytime I load the /posts/:postId page I need to get the post via the API.
I realise in the non-redux world you would just do a fetch() in the componentDidMount, and then setState() on that. But I want the posts stored in a reducer as other parts of the app may call actions that modify those posts (say for example a websocket or just a complex redux-connected component).
One approach I've seen people use is an "active" item in their reducer, like this example: https://github.com/rajaraodv/react-redux-blog/blob/master/public/src/reducers/reducer_posts.js
Whilst this is OK, it necessitates that each component that loads the active post must have a componentWillUnmount action to reset the active post (see resetMe: https://github.com/rajaraodv/react-redux-blog/blob/master/public/src/containers/PostDetailsContainer.js). If it did not reset the active post, it will be left hanging around for when the next post is displayed (it will probably flash for a short time whilst the API call is made, but it's still not nice). Generally forcing every page that wants to look at a post to do a resetMe() in a componentWillUnmount fells like a bad-smell.
So does anyone have any ideas or seen a good example of this? It seems such a simple case, I'm a bit surprised I can't find any material on it.
How to do it depends on your already existing reducers, but i'll just make a new one
reducers/post.js
import { GET_ALL_POSTS } from './../actions/posts';
export default (state = {
posts: []
}, action) => {
switch (action.type) {
case GET_ALL_POSTS:
return Object.assign({}, state, { posts: action.posts });
default:
return state;
}
};
It is very easy to understand, just fire an action to get all your posts and replace your previous posts with the new ones in the reducer.
Use componentDidMount to fire the GET_ALL_POSTS action, and use a boolean flag in the state to know if the posts where loaded or not, so you don't reload them every single time, only when the component mounts.
components/posts.jsx
import React from 'react';
export default class Posts extends React.Component {
constructor(props) {
super(props);
this.state = {
firstLoad: false
};
}
componendDidMount() {
if (!this.state.firstLoad) {
this.props.onGetAll();
this.setState({
firstLoad: true
});
}
}
// See how easy it is to refresh the lists of posts
refresh() {
this.props.onGetAll();
}
render () {
...
// Render your posts here
{ this.props.posts.map( ... ) }
...
}
}
We're just missing the container to pass the posts and the events to the component
containers/posts.js
import { connect } from 'react-redux';
import { getPosts } from './../actions/posts';
import Posts from './../components/posts.jsx';
export default connect(
state => ({ posts: state.posts }),
dispatch => ({ onGetAll: () => dispatch(getPosts()) })
);
This is a very simple pattern and I've used it on many applications
If you use react-router you can take advantage of onEnter hook.

Resources