Make a http call with axios in the nuxtServerInit action - javascript

I'm working on a static website fetching content from the WordPress API.
On the menu of the website, I want the content to be save on a nuxt store, and available on the nav component.
I reed the doc of the nuxt server and the nuxtServerInit action, but I didn't find a nice example of how to make a axion call inside this action, and be able to fetch the store on the component.
I find this, but it's not working .. https://github.com/nuxt/nuxt.js/issues/2307
Thanks a lot for your help.

Try this
store/index.js
export const state = () => ({
data: null
})
export const actions = {
// nuxtServerInit is called by Nuxt.js before server-rendering every page
async nuxtServerInit({ commit, dispatch }) {
await dispatch('storeDispatchFunc')
},
// axios...
async storeDispatchFunc({ commit }) {
const { data } = await this.$axios.get('/api/wp....')
commit('SET_DATA', data)
},
}
export const mutations = {
SET_DATA(state, theData) {
state.data = theData
}
}

Related

How to pass data in slug.js Reactjs

I am new in Nextjs, i am trying to integrate [slug.js] page, i want to know that how can we manage/get data in sidebar (similar blogs) ? in other words for blog details i used "get static path" and "props", But now i want to pass "current slug" ( to API) so i can fetch all blogs with this blog category,How can i do this ?
Client-side approach:
Since you pass the post as page-props via getStaticProps, you can either take the slug from there (if it's included in your data model), or extract the slug from the url via next's useRouter hook in case you want to do client-side fetching:
import axios from "axios"; // using axios as an example
import { useRouter } from "next/router";
const Component = () => {
const [similarPosts, setSimilarPosts] = useState([]);
const router = useRouter();
const { slug } = router.query;
const getSimilarPosts = async () => {
if (!router.isReady() || !slug) return [];
const { data } = await axios.get("/api/similar-posts-route/" + slug);
return data;
};
useEffect(() => {
if (similarPosts.length > 0) return;
(async () => {
const posts = await getSimilarPosts(); // assuming API returns an array of posts as data.
setSimilarPosts(posts);
})();
}, []);
return <div>Similar posts: {JSON.stringify(similarPosts)}</div>;
};
[...]
Server-Side approach (preferred):
I believe it would be a better approach to directly fetch similar posts inside getStaticProps to reduce API calls and for a better UX.
Inside getStaticProps you can take the slug from context.params and fetch all similar posts directly from your database/CMS, and pass them directly as props to your page component:
export async function getStaticProps({ params }) {
const { slug } = params;
// fetch similar posts directly from the database using the slug (don't call the API, it's not up yet during build phase)
const similarPosts = await executeDatabaseQueryForSimilarPosts(slug);
// [...] fetch the rest of the page props
return {
props: {
similarPosts,
// [...] return the rest of page props
},
revalidate: 60 * 30 // re-fetch the data at most every 30 minutes, so the posts stay up to date
};
}
// directly take all similar posts from props
const Component = ({similarPosts}) => {
return <div>Similar posts: {JSON.stringify(similarPosts)}</div>;
};

How to handle multiple dehydrated queries using react-query in next JS getServersideProps

I am using react-query in conjunction with Next JS getServerSideProps to fetch data before a page loads using the hydration method specified in the docs like this:
// Packages
import { dehydrate, QueryClient } from '#tanstack/react-query';
// Hooks
import { useGetGoogleAuthUrl, useGetMicrosoftAuthUrl } from '../hooks/auth';
import { getGoogleAuthUrl, getMicrosoftAuthUrl } from '../hooks/auth/api';
export async function getServerSideProps({ req, res }) {
const queryClient = new QueryClient();
const microsoftAuthQueryClient = new QueryClient(); // Not working
await queryClient.prefetchQuery(['getGoogleAuthUrl'], getGoogleAuthUrl);
await microsoftAuthQueryClient.prefetchQuery(['getMicrosoftAuthUrl'], getMicrosoftAuthUrl); // Not working
return {
props: {
dehydratedState: dehydrate(queryClient),
dehydratedMicrosoftAuthState: dehydrate(microsoftAuthQueryClient), // Not working
},
};
}
export default function Signin() {
const date = new Date();
const { data: googleAuthData } = useGetGoogleAuthUrl();
const { data: microsoftAuthData } = useGetMicrosoftAuthUrl();
console.log(googleAuthData); // logs actual data on mount and data is immediately available
console.log(microsoftAuthData); // logs undefined before eventually logging data after being successfully fetched with the useGetMicrosoftAuthUrl() query
return (
//Page content
);
}
How do I make it work as it is supposed to work. Is it not possible to make multiple requests in getServersideProps using react-query hydration method?
Thank you so much in advance
You would just use the same queryClient and prefetch both queries into it, then hydrate just the one:
export async function getServerSideProps({ req, res }) {
const queryClient = new QueryClient();
await queryClient.prefetchQuery(['getGoogleAuthUrl'], getGoogleAuthUrl);
await queryClient.prefetchQuery(['getMicrosoftAuthUrl'], getMicrosoftAuthUrl);
return {
props: {
dehydratedState: dehydrate(queryClient),
},
};
}
This however fetches them one after the other, so you might want to await them in Promise.all:
await Promise.all([
queryClient.prefetchQuery(['getGoogleAuthUrl'], getGoogleAuthUrl),
queryClient.prefetchQuery(['getMicrosoftAuthUrl'], getMicrosoftAuthUrl)
])

Vuex Data doesn't get updated on fetch when reloading browser (SSR) Nuxt

I found something about this bug I explained at end;
Component codes
async fetch(){ await this.$store.dispatch('bots/getBots') },
computed: { ...mapState('bots', ['bots']) },
Store codes
export const state = () => {
return {
bots: []
}
}
export const mutations = {
UPDATE_BOTS(state, bots) {
state.bots = bots
}
}
export const actions = {
getBots({commit}) {
this.$axios.$get('url', {headers: {uid: '12345'}})
.then(res => {
commit('UPDATE_BOTS',res.robots)
})
.catch(e => {
console.log(e)
})
}
}
Issue: When moving between pages via nuxt-link data loads perfectly but when I reload the page bots state is empty...
Found Issue:
I use nuxt-auth and I had one plugin for checking status of axios request that if it was 401 unauthorized I logout user if he was loggedIn, So status undefined error was from here but I commented the plugin codes and I got other error from nuxt-auth that causes that problem I had So I related that issue in other question u can see it here:
Nuxt-Auth Bug: Looks for autherization in any get request that has headers config
It is the expected behavior. Vuex state is kept in memory and when you reload the page it gets purged.
Instead of this state
export const state = () => {
return {
bots: []
}
}
try this
export const state = () => ({
bots: []
})

Next JS and Vercel - development vs production

I’ve built a basic movie DB app in Next JS to see how the framework works. It’s an app that allows you to perform CRUD operations to firebase, utilising the NextJS API endpoints.
I have the app working fine in development, however it does not work at all once to Vercel. I was wondering if anyone can shed some light?
Here is the first 'get all data' call upon initialisation. The other API calls follow the same pattern. None work once deployed.
My index page has this getInitialProps function…
Home.getInitialProps = async () => {
const categories = await getCategories()
const movies = await getMovies()
const images = movies.map(movie => {
return {
id: `image-${movie.id}`,
url: movie.cover,
name: movie.name
}
})
return {
movies,
images,
categories
}
}
This fires off the getMovies function here…
export const getMovies = async () => {
const res = await axios.get('http://localhost:3000/api/movies')
return res.data
And the API endpoint it hits looks like this…
import firebase from '../../lib/firebase';
export default async(req, res) => {
const moviesRef = firebase
.collection('movies');
const snapshot = await moviesRef.get();
const movies = [];
snapshot.forEach(doc => {
movies.push({ id: doc.id, ...doc.data() })
})
res.json(movies)
Thanks in advance!
you should use your server link, not localhost.
You shouldn't hardcode http://localhost:3000 in the request's URL. You should omit it altogether since you're using Next.js API routes (same-origin).
export const getMovies = async () => {
const res = await axios.get('/api/movies')
return res.data
}
Edit: The above solution would work with API routes if the request was happening on the client-side only.
Since the request is made in getInitialProps, you should simply move the logic in your API route to a separate function (could very well be getMovies in this case) and call that directly in getInitialProps instead.
export const getMovies = async () => {
const moviesRef = firebase.collection('movies');
const snapshot = await moviesRef.get();
const movies = [];
snapshot.forEach(doc => {
movies.push({ id: doc.id, ...doc.data() })
});
return movies;
}

Vuex state not updating data

I am using Vuex with axios to fetch data from my backend. But somehow the state property userName is not updating in my Vue Single File Component(SFC).
approot.js
state
const state = {
userName: 'foo'
};
getter
const getters = {
getUserName: (state) => state.userName
};
Single File Component
<template>
<div id="navbar">
//cut for brievity
<span>{{getUserName}}</span>
</template>
<script>
import {mapGetters} from 'vuex'
export default {
name: 'navbar',
computed: mapGetters(['getNumberOfJobMessages','getUserName']),
//cut for brievity
}
</script>
<style scoped>
//cut for brievity
</style>
Action fetching data with axios from the backend
const actions = {
async fetchMenuData({ commit }) {
//fetch data from api controller
const response = await axios.get('../api/Menu/GetMenu');
console.log(response.data.userName); //not undefined
commit('setMenuData', response.data);
}
}
Mutation setting state variables
const mutations = {
setMenuData(state, menuData) {
console.log(menuData.userName); //not undefined
state.userName = menuData.userName;
console.log(state.userName); //not undefined
}
}
Problem
When my single file component calls getUserName it always renders 'foo', the hardcoded value. Im quite baffled by this, since the rest of my state variables are set with the same pattern, and my components have no problems getting them.
Anyone who knows whats going wrong or can see a flaw in my code? It would be highly appreciated.
Use mutations to only set data. and other things do on action. like:
Action:
const actions = {
async fetchMenuData({ commit }) {
const response = await axios.get('../api/Menu/GetMenu');
let userName = response.data.userName;
commit('setUserName', userName);
}
}
And mutations:
const mutations = {
setUserName(state, userName) {
state.userName = userName;
}
}
Dont forget to dispatch the function fetchMenuData
Properly not sure, why this happens. But, I faced this problem and solved by this way.
axios.get('../api/Menu/GetMenu')
.then(({ data }) => {
commit('setUserName', data.userName);
}).catch(error => { })
It is better to make a commit in then()

Categories