Why axios request not working inside vuejs (nuxt.js) methods - javascript

I have installed axios inside my nuxt.js application. Here my configuration file code:
File: nuxt.config.js
modules: [
'#nuxtjs/vuetify',
'#nuxtjs/axios',
],
axios: {
// proxyHeaders: false
}
Here my example working code:
export default {
data() {
return {
ip: ''
}
},
async asyncData({ $axios }) {
const ip = await $axios.$get('http://icanhazip.com')
return { ip }
}
}
And here my not working code:
export default {
data() {
return {
ip: ''
}
},
methods: {
async asyncData() {
const ip = await this.$axios.$get('http://icanhazip.com')
this.ip = ip
}
}
}
Why inside methods axios request not working?

You cannot call asyncData in you methods object. asyncData is for pre rendering only.
Rename your function to something else and it should be fine:
export default {
data() {
return {
ip: ''
}
},
methods: {
async getData() {
const ip = await this.$axios.$get('http://icanhazip.com')
this.ip = ip
}
}
}
Also when you are using asyncData as in your top example, you should not initialise "ip" in your data function. What is returned from asyncData is merged into data anyway.

AsyncData method will be called everytime before loading the page also note that asyncdata is only available in page component in nuxt. You don't have access to the component instance through this inside asyncData because it is called before initiating the component. You can use the returned data from asyncData data in your template without initialising in your data.
Nuxt asyncData

Related

How to pass a parameter in getStaticProps in Nextjs

I just want to ask how can I call an API when a user "click the search button" and display the appropriate result in NextJS. Thank you!
This is the API I'm using https://www.themealdb.com/api/json/v1/1/search.php?s=Steak and note the "Steak" word is the food I want to see.
Here is my url in development mode http://localhost:3000/search/steak/.
I want to pass the "steak" in getStaticProps and pass the result of getStaticProps in my component.
export const getStaticProps = async () => {
const res = await axios.get(
'https://www.themealdb.com/api/json/v1/1/search.php?s=Steak'
);
return {
props: {
meals: res.data,
},
};
};
I think you can't do it. GetStaticProps render the page at build time, so you can't render a page based on user request.
I suggest you to read this docs, section 'when I should use GetStaticProps'.
You can use react state, or GetServerSideProps (read the same docs).
You can also static render a bunch of page using GetStaticPath and pass, for example, the 10 most searched foods.
You can do this with getStaticPaths if you are using dynamic routes.
You can use search/[slug].js as a dynamic route in your file based routing.
Then, in [slug].js you would have something like:
export default function Page({ response }) {
return <div>{JSON.stringify(response)})</div>
}
// get all the possible paths for the individual ingredients
export async function getStaticPaths() {
const data = await axios.get(
'www.themealdb.com/api/json/v1/1/list.php?i=list'
);
return {
paths: data.meals.map((ingredient) => ({
params: { slug: ingredient.strIngredient.toString().toLowerCase. },
})),
fallback: false, // can also be true or 'blocking'
}
}
export async function getStaticProps({ params }) {
const { slug } = params
const response = await axios.get(
`https://www.themealdb.com/api/json/v1/1/search.php?s=${slug}`
);
return {
props: {
response
},
}
}

How to use cookie inside `getServerSideProps` method in Next.js?

I have to send current language on endpoint. But getting language from Cookie returns undefined inside getServerSideProps.
export async function getServerSideProps(context) {
const lang = await Cookie.get('next-i18next')
const res = await fetch(`endpoint/${lang}`)
const data = await res.json()
return {
props: { data },
}
}
export default Index;
What is the proper way to get cookie inside getServerSideProps?
You can get the cookies from the req.headers inside getServerSideProps:
export async function getServerSideProps(context) {
const cookies = context.req.headers.cookie;
return {
props: {},
};
}
You could then use the cookie npm package to parse them:
import * as cookie from 'cookie'
export async function getServerSideProps(context) {
const parsedCookies = cookie.parse(context.req.headers.cookie);
return { props: {} }
}
To avoid having to parse the cookies string from context.req.headers.cookie, Next.js also provides the cookies as an object which can be accessed with context.req.cookies.
export async function getServerSideProps(context) {
const lang = context.req.cookies['next-i18next']
// ...
}
From getServerSideProps documentation:
The req in the context passed to getServerSideProps provides built in
middleware that parses the incoming request (req). That middleware is:
req.cookies - An object containing the cookies sent by the request.
Defaults to {}
You can use parseCookies function with cookie package
import cookie from "cookie"
function parseCookies(req){
return cookie.parse(req ? req.headers.cookie || "" : document.cookie);
}
And then get access like that.
export async function getServerSideProps({ req} ) {
const cookies = parseCookies(req);
// And then get element from cookie by name
return {
props: {
jwt: cookies.jwt,
}
}
}
If you are using Axios this is very simple
This will work inside getServerSideProps method. You can't get access to the cookie by using withCredentials because this is on the server.
const { token } = context.req.cookies;
const response = await axios.get('/staff/single', {
headers: { Cookie: `token=${token};` },
});
or try (This will work on the client)
const response = await axios.get('/staff/single', {
headers: { withCredentials: true },
});
how are you doing?
you can use Something like this :
export async function getServerSideProps(context) {
console.log(context.req.cookies)
}
so easy and so beautifuly!

Create Nuxt.js list with async data & axios

I try to load data from Json to vue component using this tutorial:
https://nuxtjs.org/guide/async-data/
This is my code:
<li class="item" v-for="post in posts" v-bind:key="post.id">
<nuxt-link :to="....">
{{post.id}}. {{post.title}}
</nuxt-link>
</li>
import axios from "axios";
export default {
async data () {
let { data } = await axios.get(`http://jsonplaceholder/`)
return { posts: data } // Console: property post is not defined
}
}
Tell me please, what's wrong?
You can do this based on Nuxt asyncData and the context guide, i.e.:
export default {
async asyncData(context) {
let response = await context.app.$axios.$get(`http://jsonplaceholder/`)
return { posts: response }
}
}
according to nuxtjs document
async asyncData ({ params }) {
let { data } = await axios.get(`https://my-api/posts/${params.id}`)
return { title: data.title }
}
in your case this should be
async asyncData () {
let { data } = await axios.get(`http://jsonplaceholder/`)
return { posts: data } // Console: property post is not defined
}
Explaining more sid heart's reply:
Function name is "asyncData" not async data. You are using async await you can use like this:
import axios from "axios";
export default {
// Also define data function and define posts property
data() {
return {
posts: {}
}
},
async asyncData () {
let { data } = await axios.get(`http://jsonplaceholder/`)
return { posts: data } // Console: property post is not defined
}
}

javascript - call exported function from another class

Here's the scenario: There is a file called api.js which has method api() to make api calls. There is another class called AutoLogout which has functionality to show autologout modal and logging out user after certain time in case of no activity. These works fine.
index.js in ../services
export { default as api } from './api';
// export { api, onResponse } from './api'; tried this as well
export { default as userService } from './userService';
api.js
import userService from './userService';
export function onResponse(response) {
// returns response to calling function
return response;
}
async function api(options) {
const settings = Object.assign(
{
headers: {
'content-type': 'application/json',
'x-correlation-id': Math.random()
.toString(36)
.substr(2),
},
mode: 'cors',
credentials: 'include',
body: options.json != null ? JSON.stringify(options.json) : undefined,
},
options,
);
const response = await window.fetch(`/api/v0${options.endpoint}`, settings);
// calling onResponse() to send the response
onResponse(response);
if (response.status === 403) return userService.logout();
if (response.status > 299) throw new Error();
if (response.status === 204) return true;
return response.json ? response.json() : false;
}
export default api;
Now, in response header I've "x-expires-at" and I want to use it in autologout. So, that if api call is made the user token resets.
auto-lougout.js
import { userService, api } from '../services';
// import { userService, api, onResponse } from '../services'; tried this as well
export default class AutoLogout {
constructor() {
super();
if (!userService.getUser()) userService.logout();
// here I am not able to call onResponse() from api.js
// getting response received from onResponse()
api.onResponse((resp) => { console.log(resp.headers.get('x-expires-at'))});
}
}
Trying to implement as an example given in this article:
https://zpao.com/posts/calling-an-array-of-functions-in-javascript/
Here I cannot use export { api, onResponse }; as api is already being used at multiple places in whole project.
How do I call onResponse function in one js file from another class in another js file ? Am I using callback correctly here ? If not, how to use callback correctly in such scenario ?
Here I cannot use export { api, onResponse }; as api is already being used at multiple places in whole project.
The correct import/export syntax for your project would be
// api.js
export function onResponse() { … }
export default function api() { … }
// index.js
export { default as userService } from './userService';
export { default as api, onResponse } from './api';
// elsewhere
import { userService, api, onResponse } from '../services';
// use these three
Am I using callback correctly here?
No, not at all. onResponse should not be a function declared in your api.js file, and it should not be exported from there - sparing you all the above hassle.
If not, how to use callback correctly in such scenario?
Make the callback a parameter of the function that uses it:
export default async function api(options, onResponse) {
// ^^^^^^^^^^
const settings = Object.assign(…);
const response = await window.fetch(`/api/v0${options.endpoint}`, settings);
onResponse(response);
…
}
Then at the call of the api function, pass your callback as an argument:
api(options, resp => {
console.log(resp.headers.get('x-expires-at'));
});

How to get Next.js and redux-api to work (with next-redux-wrapper)

I’m struggling to get server-side rendering (SSR) to work with redux-api. The app works fine with just client-side rendering (CSR).
For SSR to work, I need the data to be available in Next.js’ getInitialProps function. I’m trying to use next-redux-wrapper to bind it together.
Current status:
class ShowLessonPage extends React.Component {
static async getInitialProps ({store, isServer, pathname, query}) {
console.log(`getInitialProps`, {store, isServer, pathname, query});
const { dispatch } = store;
const lessonSlug = query.lessonSlug;
// Get one Lesson
dispatch(reduxApi.actions.oneLesson({ id: `slug=${lessonSlug}` }));
}
render() {
console.log('render', this.props.oneLesson);
const lesson = this.props.oneLesson.data;
//...
}
//.....
}
const createStoreWithThunkMiddleware = applyMiddleware(thunk)(createStore);
const reducer = combineReducers(myReduxApi.reducers); // redux-api
const makeStore = function (state, enhancer) {
return createStoreWithThunkMiddleware(reducer, state);
}
const mapStateToProps = function (state) {
return { oneLesson: state.oneLesson };
};
// withRedux = next-redux-wrapper
const ShowLessonPageConnected = withRedux({ createStore: makeStore, mapStateToProps: mapStateToProps })(ShowLessonPage)
export default ShowLessonPageConnected;
I at least get store into getInitialProps now, but I get a strange Error: only absolute urls are supported message that I didn’t have in my CSR (pre-withRedux) version of the app. And this.props.oneLesson.data is of course empty.
makeStore is getting a state=undefined on the server generated calls, maybe that’s a clue.
I’m also open to replacing redux-api with something else that works similarly.
UPDATE 1: by making all URLs full, Redux is now hitting my API endpoint. However, for 1 page reload it calls makeStore no less than 3 times, and only the first call contains the correct slug, see console output:
makeStore { state: undefined, reqParams: { lessonSlug: 'tyrannosaurus-rex' } }
getInitialProps { query: { lessonSlug: 'tyrannosaurus-rex' } }
API: GET request: { _id: 'slug=tyrannosaurus-rex' }
makeStore { state: undefined, reqParams: { lessonSlug: 'undefined' } }
getInitialProps { query: { lessonSlug: 'undefined' } }
API: GET request: { _id: 'slug=undefined' }
makeStore { state: undefined, reqParams: { lessonSlug: 'undefined' } }
getInitialProps { query: { lessonSlug: 'undefined' } }
API: GET request: { _id: 'slug=undefined' }
UPDATE 2: A breakthrough: returning a promise from getInitialProps makes SSR work. Now client-side rendering is acting up, funny enough.
static async getInitialProps ({store, isServer, pathname, query}) {
const { dispatch } = store;
const lessonSlug = query.lessonSlug;
const resultPromise = await dispatch(reduxApi.actions.oneLesson({ id: `slug=${lessonSlug}` }));
return resultPromise;
}
I managed to solve it, after a full day’s hair-pulling.
There was a number of issues before it worked as it should:
Absolute URLs. The client-only code had no issue with relative URLs, but the server did.
getInitialProps must return a Promise to the results (see below).
My data object (oneLesson) ended up on this.state, not this.props as I expected (for my use case I don’t really care as long as I can render it both on server and client).
Here’s the final version of getInitialProps:
static async getInitialProps ({store, isServer, pathname, query}) {
const { dispatch } = store;
const lessonSlug = query.lessonSlug;
const resultPromise = await dispatch(reduxApi.actions.oneLesson({ id: `slug=${lessonSlug}` }));
return resultPromise;
}
Here’s a complete working example of Next.js, redux-api, and next-redux-wrapper working in harmony:
https://github.com/tomsoderlund/nextjs-express-mongoose-crudify-boilerplate

Categories

Resources